![](/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.