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

标签 java spring spring-boot spring-security spring-security-oauth2

因此,我目前正在为我的组织重构后端代码,为将来的升级做准备。它目前运行良好,只是代码变得相当困惑,因为这个组织中存在大量的角色和授权。

所以我们这里的后端堆栈是一个简单的 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/

相关文章:

java - 关于方法上的 Spring @Transactional 注释的一些说明

spring-boot - Spring Boot 2 转换持续时间 java 8 application.properties

java - 用于配置文件组合的 Spring boot YAML 配置

gradle - Spring-Boot项目的Gradle Maven-publish引发错误:找不到父项:org.springframework.boot:项目的spring-boot-starter-parent

java - 一个同步块(synchronized block)与多个 AtomicInteger 增量相比

java - 有人能找出我的代码有什么问题吗?

java - 在迭代其 entrySet 时修改 map

java - Spring Boot – 未找到 JSP View

java - Android:无法为标题设置 TextView

java - 使用 Java 连接到 heroku Postgres 数据库