gpt4 book ai didi

java - 如何仅为用户自己的端点启用请求

转载 作者:行者123 更新时间:2023-11-30 01:57:49 26 4
gpt4 key购买 nike

我有一个像这样的休息端点:/用户/{userId}/某事

我使用oauth2实现了身份验证。我的 WebSecurityConfig 如下所示:

protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll();
}

我怎样才能只允许用户访问自己的端点(例如,ID 100的用户只能访问/users/100/something),而无法看到另一个端点(例如/user/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);
}

请注意,userId 必须在某处提供,可以是 @PathVariable@RequestParam。然后,Spring security 将检查当前用户是否与提供的 userId 匹配,否则返回 403

完整示例可用 here并已根据您的目的在该问题中进行了修改。

SpEL

您还可以使用 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 将注入(inject)当前主体。默认情况下,身份验证绑定(bind)到当前执行线程,如果请求已处理或遇到异常,身份验证将被重置。

关于java - 如何仅为用户自己的端点启用请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53788165/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com