【问题标题】:Best way to implement authorization per group in spring security在春季安全中实现每组授权的最佳方法
【发布时间】:2020-06-21 13:24:29
【问题描述】:

我正在尝试根据用户在组中的角色为用户授权某些操作的最佳方法。
例如,Peter 在 A 组中具有管理员角色,因此他可以踢 A 组中的成员和 B 组中的成员角色,因此他只能读取 B 组中的内容。
this is what model of user group relationship looks like.
有没有比在 UserDetails 中加载组角色更好的方法来实现授权:

(for (GroupUser groupuser: user.getGroupUsers()) {
   authorities.add(new SimpleGrantedAuthority('Group_'+groupuser.getId().getGroupId()+'_'+groupuser.getRole()));} 

【问题讨论】:

  • 表格设计有一个小问题。您在关系表中创建了 ROLE。如此多对多的关系,你为什么要在关系表中保留角色?
  • 角色是指特定组中的用户角色而不是一般角色@Gurkanİlleez
  • 以我的拙见,分组角色而不是分组用户怎么样。用户可以拥有多个角色(授权),例如 read_b_content、read_a_content、write_a_content。当您从组中踢出用户时,您可以删除授权。

标签: spring spring-boot spring-security


【解决方案1】:

这是ABAC权限模型,其安全决策不仅取决于用户的信息,还取决于受保护资源的状态/属性。

就 spring security 而言,最好使用@PreAuthorize / @PostAuthorize / @PostFilter 实现,这允许您使用 SpEL 表达式以声明方式定义安全逻辑,该表达式最终将评估为 true/错误的。在 SpEL 中,您可以访问方法的输入参数和返回对象,该方法执行您想要应用安全性的用例,甚至可以引用 spring bean 来调用其方法进行评估。

例如,您可以执行以下操作:

@PreAuthorize("@authzService.isAllowToKickMember(principal , #userToKick)")
public void kickMemeber(User userToKick){
    
}


@Service
public class AuthzService{

    public boolean isAllowToKickMember(User currentUser , User userToKick){
        //check if current user can kick a given user
    }
}

如需指点,请查看this

【讨论】:

  • 我喜欢这个答案。但是,如果您还基于相同的额外规则隐藏/显示页面上的部分,那么您将为同一请求执行两次规则。如果这些规则的执行成本很高,则可能是性能问题。因此为避免这种情况,SecurityContext 本身在创建时应该具有基于角色的权限 + 基于属性的权限。 (我在一个项目中通过执行创建安全上下文的过滤器中的规则,但该项目不是基于 Spring 的。)
  • 是的。存储在SecurityContext 中的用户对象应包含在确定安全决策时有用的用户信息。对于执行两次的问题,我不确定您是否正确理解您的意思。当我正在编写通用代码时,我的后端 API 总是需要验证安全性,即使 ui 已经检查了它,因为后端 api 应该被设计为供其他客户端使用,而不仅仅是 ui。
  • 我错过了这个。我的意思是必须对表达式进行评估,一次是在调用 kickMemeber 方法之前,一次是在同一应用程序实例中渲染模板期间。但是,如果这些规则在过滤器中进行评估并添加为动态权限,则该规则不会运行两次
猜你喜欢
  • 2015-02-05
  • 1970-01-01
  • 2011-05-15
  • 1970-01-01
  • 2020-01-11
  • 1970-01-01
  • 2018-08-12
  • 2013-12-22
相关资源
最近更新 更多