spring-security 在Spring Security中实现大量级联角色和权限的更好方法?

nwnhqdif  于 2022-11-11  发布在  Spring
关注(0)|答案(1)|浏览(154)

因此,我目前正在为我的组织重构后端代码,为将来的升级做准备。它目前运行良好,只是代码变得相当混乱,因为这个组织中存在大量的角色和授权。
我们的后端堆栈是一个简单的springboot Rest API,我们使用第三方Oauth身份验证提供程序作为安全提供程序。
因此,对于每一个进入的请求,我们都有一个spring安全过滤器,它从authentication 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
  • 财务二
  • 财务1

其中财务管理员拥有财务3的所有权限+自己的专属权限等等。
rest API中的每个端点最终看起来如下所示:

@PreAuthorize("hasAuthority('FinanceHead') or hasAuthority('FinanceAdmin') or hasAuthority('Finance3') or hasAuthority('Finance2') or hasAuthority('Finance1')")

许多端点是多部门的,有20多个hasAuthorities。不要误解我,这目前工作正常,但它成为一个痛苦的改变一个角色,然后我必须搜索所有端点,并改变每一个。有更好的方法来做到这一点吗?
我在想,是否有可能将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);
    }
}

有没有更好的方法?

zbq4xfa0

zbq4xfa01#

这是我如何结束了这一点,感谢M.代努姆向我展示了 Spring 安全中存在的层次角色。
我所做的就是创建角色层次结构,如下所示:

@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。

相关问题