![](/img/trans.png)
[英]User can view everyone's profile but only edit its own, how to implement in Shiro?
[英]How can I enable request only for user's own endpoint
我有一个这样的休息端点:/ users / {userId} / something
我使用oauth2实现了身份验证。 我的WebSecurityConfig看起来像这样:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll();
}
如何仅允许用户访问自己的终结点(例如,ID为100的用户只能访问/users/100/something
)而无法看到另一个终结点(例如/users/200/something
)?
这可能吗?
有很多方法可以解决此问题,但我已经提出了三种解决该问题的方法。
我建议使用基于自定义安全性的注释方法。 这将涉及实现自定义安全性表达式,相关的表达式处理程序和方法安全性配置。 如果这对您来说太多了,那么下一个方法会更简单一些。
public class UserIdentityMethodSecurityExpressionRoot
extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
public UserIdentityMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean userIdentity(Long userId) {
User user = ((UserPrincipal) this.getPrincipal()).getUser();
return user.getId() == userId;
}
}
然后,可以使用新创建的安全性表达式对其余端点或服务方法进行注释:
@PreAuthorize("userIdentity(#userId)")
@GetMapping
@ResponseBody
public Resource fineOne(@PathVariable Long userId) {
return resourceService.findOne(id);
}
请注意,必须在某处以@PathVariable
或@RequestParam
形式提供userId
。 然后,Spring Security将检查当前用户是否与提供的userId
匹配,否则返回403
。
完整的示例在此处可用,并且已针对您的目的在此问题中进行了调整。
您还可以使用SpEL,这有点简单:
@PreAuthorize("#userId == principal.getId()")
@GetMapping
@ResponseBody
public Resource fineOne(@PathVariable Long userId) {
return resourceService.findOne(id);
}
您也可以自己完成所有工作,并获得更快的结果,而无需使用SecurityContextHolder
定义自定义表达式。
public static void checkUserIdentity(Long userId) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// user did not provide a token
if(auth == null) {
throw new AccessDeniedException();
}
UserDetails details = (UserDetails) auth.getPrincipal();
if(userId != details.getId()) {
throw new AccessDeniedException();
}
}
并像这样使用它:
@GetMapping
@ResponseBody
public Resource fineOne(@PathVariable Long userId) {
SecurityUtils.checkUserIdentity(userId)
return resourceService.findOne(id);
}
为什么这样做? 如果您已经正确设置了Spring安全性,那么SecurityContextHolder
将注入当前的主体。 默认情况下,身份验证绑定到当前的执行线程,如果请求已处理或遇到异常,则将重置身份验证。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.