因此,我目前正在为我的组织重构后端代码,为将来的升级做准备。它目前运行良好,只是代码变得相当困惑,因为这个组织中存在大量的角色和授权。
所以我们这里的后端堆栈是一个简单的 springboot Rest API,我们使用第三方 Oauth 身份验证提供程序作为我们的安全提供程序。
因此,对于每个传入的请求,我们都有一个 spring 安全过滤器,它从身份验证 header JWT 中获取用户角色,并根据它分配授权。
List<GrantedAuthority> authorities = new ArrayList<>();
for (Map.Entry<String,Object> role : user.getCustomClaims().entrySet()) {
authorities.add(new SimpleGrantedAuthority((String) user.getCustomClaims().get("role")));
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getUid(), authorities));
filterChain.doFilter(request, response);
现在“问题”的存在是因为存在的角色和身份验证的数量,8 年前这家公司最初是一家只有 10 名员工的简单初创公司,现在是一家拥有 500 ~ 名员工的中型公司。因此角色和权限的数量呈指数级增长。
以财务部为例,我们目前有5级权限,而且都是级联的。
- 财务主管
- 财务管理员
- 财务 3
- 财务 2
- 财务 1
其中Finance Admin拥有Finance 3的所有权限+自己专属的权限等。
其余 API 中的每个端点最终看起来像这样:
@PreAuthorize("hasAuthority('FinanceHead') or hasAuthority('FinanceAdmin') or hasAuthority('Finance3') or hasAuthority('Finance2') or hasAuthority('Finance1')")
许多端点是多部门的,拥有 20 多个 hasAuthorities。不要误会我的意思,这目前工作正常,但改变一个角色变得很痛苦,因为 id 必须搜索所有端点并更改每个端点。有更好的方法吗?
我在想是否可以将 GrantedAuthority 对象重写成这样:
public class GrantedAuthority {
String role; ("Finance","Logistics", etc)
int authLevel; (1,2,3,4,5)
}
这样我就可以为每个主要端点执行 hasRole("Finance") at 然后使用 hasAuth(>3) 用于任何其他端点中的每个方法,如下所示:
@PreAuthorize("hasRole('Finance')
@CrossOrigin
@RestController
@RequestMapping("/test")
public class test {
@PreAuthorize("hasAuthority('authLevel > 3')
@GetMapping
public ResponseEntity<String> ping() {
return new ResponseEntity<>("test", HttpStatus.OK);
}
}
有更好的方法吗?
最佳答案
这就是我最终的处理方式,感谢 M. Deinum 向我展示了 Spring Security 中存在分层角色。
所以我所做的就是像这样创建角色层次结构:
@Bean
public RoleHierarchyImpl roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy(
"ROLE_BOSS > ROLE_FINANCE_HEAD > ROLE_FINANCE_ADMIN > ROLE_FINANCE_3 > ROLE_FINANCE_2 > ROLE_FINANCE_1"
return roleHierarchy;
}
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
return defaultWebSecurityExpressionHandler;
}
然后像这样将它们添加到我的安全配置中:
http
.authorizeRequests().anyRequest().authenticated()
.expressionHandler(webExpressionHandler())
所以现在而不是
@PreAuthorize("hasAuthority('FinanceHead') or hasAuthority('FinanceAdmin') or hasAuthority('Finance3') or hasAuthority('Finance2') or hasAuthority('Finance1')")
@GetMapping("/test")
public ResponseEntity<String> test1() {
return new ResponseEntity<>("Test", HttpStatus.OK);
}
我可以走了
@PreAuthorize("hasRole('ROLE_ADMIN_3')")
@GetMapping("/test")
public ResponseEntity<String> test1() {
return new ResponseEntity<>("Test", HttpStatus.OK);
}
如果请求具有以下任何角色:
ROLE_BOSS, ROLE_FINANCE_HEAD, ROLE_FINANCE_ADMIN, ROLE_FINANCE_3
请求将完成,否则抛出 403。
关于java - 在 Spring Security 中实现大量级联角色和权限的更好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72810153/