Spring Security中角色与GrantedAuthority的区别

Chi*_*may 209 java spring spring-mvc spring-security

有概念和实现Spring Security的,如GrantedAuthority界面得到一个权威授权/控制的访问.

我希望这是允许的操作,例如createSubUsersdeleteAccounts,我允许管理员(带角色ROLE_ADMIN).

我在网上看到的教程/演示让我感到困惑.我尝试连接我读到的内容,但我认为我们可以互换地对待这两者.

我看到hasRole消费了一个GrantedAuthority字符串?我肯定在理解上做错了.这些概念在Spring Security中是什么?

如何存储用户的角色,与该角色的权限分开?

我也在查看在org.springframework.security.core.userdetails.UserDetails身份验证提供程序引用的DAO中使用的接口,它使用了一个User(注意最后的GrantedAuthority):

public User(String username, 
            String password, 
            boolean enabled, 
            boolean accountNonExpired,
            boolean credentialsNonExpired, 
            boolean accountNonLocked, 
            Collection<? extends GrantedAuthority> authorities)
Run Code Online (Sandbox Code Playgroud)

或者还有其他方法可以区分其他两个吗?或者它不受支持,我们必须自己制作?

Jam*_*mes 331

将GrantedAuthority视为"权限"或"权利".那些"权限"(通常)表示为字符串(使用该getAuthority()方法).这些字符串可让您识别权限,并让您的选民决定是否允许访问某些内容.

您可以将不同的GrantedAuthority(权限)授予用户,方法是将它们放入安全上下文中.您通常通过实现自己的UserDetailsS​​ervice来执行此操作,该UserDetailsS​​ervice返回返回所需GrantedAuthorities的UserDetails实现.

角色(在许多示例中使用它们)只是"权限",其命名约定表明角色是以前缀开头的GrantedAuthority ROLE_.没有别的了.角色只是一个GrantedAuthority - 一个"权限" - 一个"权利".您在spring security中看到很多地方,其ROLE_前缀的角色专门处理,例如在RoleVoter中,其中ROLE_前缀用作默认值.这允许您提供不带ROLE_前缀的角色名称.在Spring security 4之前,对"角色"的这种特殊处理并未得到非常一致的遵守,权威和角色通常被视为相同(例如,hasAuthority()hasRole()).使用Spring Security 4,角色的处理较为一致,并以"角色"交易代码(如RoleVoter中,hasRole表达等)总是添加ROLE_前缀为您服务.所以hasAuthority('ROLE_ADMIN')意味着相同,hasRole('ADMIN')因为ROLE_前缀会自动添加.有关更多信息,请参阅spring security 3至4 迁移指南.

但仍然是:角色只是具有特殊ROLE_前缀的权威.因此,在春季安全3 @PreAuthorize("hasRole('ROLE_XYZ')")是一样的@PreAuthorize("hasAuthority('ROLE_XYZ')"),并在Spring Security 4 @PreAuthorize("hasRole('XYZ')")是一样的@PreAuthorize("hasAuthority('ROLE_XYZ')").

关于你的用例:

用户具有角色和角色可以执行某些操作.

您最终GrantedAuthorities可以获得用户所属的角色以及角色可以执行的操作.在GrantedAuthorities对角色有前缀ROLE_和操作都有前缀OP_.操作部门的例子是OP_DELETE_ACCOUNT,OP_CREATE_USER,OP_RUN_BATCH_JOB等角色可以ROLE_ADMIN,ROLE_USER等.

您最终可能会GrantedAuthority像在此(伪代码)示例中那样实现您的实体:

@Entity
class Role implements GrantedAuthority {
    @Id
    private String id;

    @OneToMany
    private final List<Operation> allowedOperations = new ArrayList<>();

    @Override
    public String getAuthority() {
        return id;
    }

    public Collection<GrantedAuthority> getAllowedOperations() {
        return allowedOperations;
    }
}

@Entity
class User {
    @Id
    private String id;

    @OneToMany
    private final List<Role> roles = new ArrayList<>();

    public Collection<Role> getRoles() {
        return roles;
    }
}

@Entity
class Operation implements GrantedAuthority {
    @Id
    private String id;

    @Override
    public String getAuthority() {
        return id;
    }
}
Run Code Online (Sandbox Code Playgroud)

您在数据库中创建的角色和操作的ID将是GrantedAuthority表示形式,例如"ROLE_ADMIN","OP_DELETE_ACCOUNT"等.当用户通过身份验证时,请确保所有角色的所有GrantedAuthorities和相应的操作都是从UserDetails.getAuthorities()方法.

示例:具有标识为ROLE_ADMIN的admin角色具有分配给它的操作OP_DELETE_ACCOUNT,OP_READ_ACCOUNT,OP_RUN_BATCH_JOB.ID为ROLE_USER的用户角色具有操作OP_READ_ACCOUNT.

如果管理员登录生成的安全上下文将具有GrantedAuthorities:ROLE_ADMIN,OP_DELETE_ACCOUNT,OP_READ_ACCOUNT,OP_RUN_BATCH_JOB

如果用户记录它,它将具有:ROLE_USER,OP_READ_ACCOUNT

UserDetailsS​​ervice将负责收集这些角色的所有角色和所有操作,并通过返回的UserDetails实例中的getAuthorities()方法使它们可用.

  • 这是一个很好的答案.有一点要明确解释一点,Spring Security 4中的`hasRole('xyz')`希望你有**ROLE _**前缀,而`hasAuthority('xyz')`不要指望前缀并且准确地评估了传入的内容.我使用了这个解决方案,但由于需要**ROLE _**前缀而遇到`hasRole('OP_MY_PERMISSION')`的问题.相反,我应该使用`hasAuthority('OP_MY_PERMISSION')`,因为我没有前缀. (10认同)
  • 谢谢!我到处都在寻找为什么“ hasRole('rolename')”在Spring 4中不起作用的原因-&gt;他们的文档浏览并不很快。只需快速“查找并更换”,我就回到了正轨! (2认同)
  • @gautam:不不,这是正确的。`@PreAuthorize("hasRole('ROLE_XYZ')")` 实际上会检查是否有一个名为 `ROLE_ROLE_XYZ` 的权限,因为它为您添加了 `ROLE_` 前缀。 (2认同)

sof*_*ake 9

理解这些概念之间关系的另一种方法是将 ROLE 解释为权限的容器。

权限是针对特定操作的细粒度权限,有时还带有特定的数据范围或上下文。例如,读取、写入、管理可以表示对给定信息范围的各种权限级别。

此外,权限在请求的处理流程中深入执行,而角色在到达控制器之前通过请求过滤器方式过滤。最佳实践规定在业务层中通过控制器实施权限执行。

另一方面,ROLES 是一组权限的粗粒度表示。ROLE_READER 将仅具有读取或查看权限,而 ROLE_EDITOR 将同时具有读取和写入权限。角色主要用于http等请求处理外围的第一次筛选。... .antMatcher(...).hasRole(ROLE_MANAGER)

在请求的流程中深入实施的权限允许更细粒度的权限应用。例如,用户可能对一级资源具有读写权限,但对子资源仅具有读取权限。拥有 ROLE_READER 将限制他编辑第一级资源的权利,因为他需要写入权限来编辑此资源,但 @PreAuthorize 拦截器可能会阻止他尝试编辑子资源。

杰克


cod*_*der 7

AFAIK GrantedAuthority和角色在Spring安全性中是相同的.GrantedAuthority的getAuthority()字符串是角色(根据默认实现SimpleGrantedAuthority).

对于您的情况,您可以使用分层角色

<bean id="roleVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <constructor-arg ref="roleHierarchy" />
</bean>
<bean id="roleHierarchy"
        class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_createSubUsers
            ROLE_ADMIN > ROLE_deleteAccounts 
            ROLE_USER > ROLE_viewAccounts
        </value>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

不是你想要的精确溶胶,但希望它有所帮助

编辑:回复您的评论

角色就像是春天安全的权限.使用带有hasRole的intercept-url可以对哪个角色/权限允许的操作提供非常精细的控制.

我们在应用程序中处理的方式是,我们为每个操作(或rest url)定义权限(即角色),例如view_account,delete_account,add_account等.然后我们为每个用户创建逻辑配置文件,如admin,guest_user,normal_user.配置文件只是权限的逻辑分组,与spring-security无关.添加新用户时,会为其分配配置文件(具有所有允许的权限).现在,当用户尝试执行某些操作时,将针对用户grantAuthorities检查该操作的权限/角色.

defaultn RoleVoter也使用前缀ROLE_,因此任何以ROLE_开头的权限都被视为角色,您可以通过在角色选民中使用自定义RolePrefix并在spring security中使用它来更改此默认行为.


Jer*_*emy 5

就像其他人提到的那样,我将角色视为更精细权限的容器。

虽然我发现层次角色实现缺乏对这些细粒度权限的精细控制。
因此,我创建了一个库来管理关系并将权限作为安全上下文中的授予权限注入。

我可能在应用程序中有一组权限,例如 CREATE、READ、UPDATE、DELETE,然后与用户的角色相关联。

或更具体的权限,如 READ_POST、READ_PUBLISHED_POST、CREATE_POST、PUBLISH_POST

这些权限是相对静态的,但角色与它们的关系可能是动态的。

例子 -

@Autowired 
RolePermissionsRepository repository;

public void setup(){
  String roleName = "ROLE_ADMIN";
  List<String> permissions = new ArrayList<String>();
  permissions.add("CREATE");
  permissions.add("READ");
  permissions.add("UPDATE");
  permissions.add("DELETE");
  repository.save(new RolePermissions(roleName, permissions));
}
Run Code Online (Sandbox Code Playgroud)

您可以创建 API 来管理这些权限与角色的关系。

我不想复制/粘贴另一个答案,所以这里是关于 SO 的更完整解释的链接。
/sf/answers/4217635201/

为了重用我的实现,我创建了一个 repo。请随时贡献!
https://github.com/savantly-net/spring-role-permissions