Java Spring Security 中 Role 和 GrantedAuthority 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19525380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 18:00:57  来源:igfitidea点击:

Difference between Role and GrantedAuthority in Spring Security

javaspringspring-mvcspring-security

提问by Chinmay

There are concepts and implementations in Spring Security, such as the GrantedAuthorityinterface to get an authorityto authorize/control an access.

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

I would like that to permissible operations, such as createSubUsers, or deleteAccounts, which I would allow to an admin(with role ROLE_ADMIN).

我希望允许的操作,例如createSubUsersdeleteAccounts,我会允许管理员(具有角色ROLE_ADMIN)。

I am getting confused as the tutorials/demos I see online. I try to connect what I read, but I think we treat the two interchangeably.

我在网上看到的教程/演示感到困惑。我尝试将我读到的内容联系起来,但我认为我们可以互换对待两者。

I see hasRoleconsuming a GrantedAuthoritystring? I most definitely am doing it wrong in understanding. What are these conceptually in Spring Security?

我看到hasRole消耗一个GrantedAuthority字符串?我绝对是在理解上做错了。Spring Security 中的这些概念是什么?

How do I store the role of a user, separate from the authorities for that role?

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

I'm also looking at the org.springframework.security.core.userdetails.UserDetailsinterface which is used in the authentication-provider referenced DAO, which consumes a User(note last GrantedAuthority):

我还在查看在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)

Or is there any other way to differentiate the other two? Or is it not supported and we have to make our own?

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

采纳答案by James

Think of a GrantedAuthority as being a "permission" or a "right". Those "permissions" are (normally) expressed as strings (with the getAuthority()method). Those strings let you identify the permissions and let your voters decide if they grant access to something.

将 GrantedAuthority 视为“权限”或“权利”。这些“权限”(通常)表示为字符串(使用getAuthority()方法)。这些字符串可让您识别权限,并让您的选民决定是否授予对某些内容的访问权限。

You can grant different GrantedAuthoritys (permissions) to users by putting them into the security context. You normally do that by implementing your own UserDetailsService that returns a UserDetails implementation that returns the needed GrantedAuthorities.

您可以通过将用户置于安全上下文中来向用户授予不同的 GrantedAuthority(权限)。您通常通过实现自己的 UserDetailsS​​ervice 来实现,该服务返回 UserDetails 实现,该实现返回所需的 GrantedAuthorities。

Roles (as they are used in many examples) are just "permissions" with a naming convention that says that a role is a GrantedAuthority that starts with the prefix ROLE_. There's nothing more. A role is just a GrantedAuthority - a "permission" - a "right". You see a lot of places in spring security where the role with its ROLE_prefix is handled specially as e.g. in the RoleVoter, where the ROLE_prefix is used as a default. This allows you to provide the role names withtout the ROLE_prefix. Prior to Spring security 4, this special handling of "roles" has not been followed very consistently and authorities and roles were often treated the same (as you e.g. can see in the implementation of the hasAuthority()method in SecurityExpressionRoot- which simply calls hasRole()). With Spring Security 4, the treatment of roles is more consistent and code that deals with "roles" (like the RoleVoter, the hasRoleexpression etc.) always adds the ROLE_prefix for you. So hasAuthority('ROLE_ADMIN')means the the same as hasRole('ADMIN')because the ROLE_prefix gets added automatically. See the spring security 3 to 4 migration guidefor futher information.

角色(正如它们在许多示例中使用的那样)只是具有命名约定的“权限”,该约定表示角色是以前缀 开头的 GrantedAuthority ROLE_。没有什么了。角色只是 GrantedAuthority - “权限” - “权利”。您会在 Spring Security 中看到很多地方,其中带有ROLE_前缀的角色被特别处理,例如在 RoleVoter 中,ROLE_前缀用作默认值。这允许您提供不带ROLE_前缀的角色名称。在 Spring security 4 之前,这种对“角色”的特殊处理并未得到非常一致的遵循,并且权限和角色通常被视为相同(如您hasAuthority()hasRole())。使用 Spring Security 4,角色的处理更加一致,处理“角色”(如RoleVoterhasRole表达式等)的代码总是ROLE_为您添加前缀。所以hasAuthority('ROLE_ADMIN')意思是一样的,hasRole('ADMIN')因为ROLE_前缀是自动添加的。有关更多信息,请参阅 spring security 3 到 4迁移指南

But still: a role is just an authority with a special ROLE_prefix. So in Spring security 3 @PreAuthorize("hasRole('ROLE_XYZ')")is the same as @PreAuthorize("hasAuthority('ROLE_XYZ')")and in Spring security 4 @PreAuthorize("hasRole('XYZ')")is the same as @PreAuthorize("hasAuthority('ROLE_XYZ')").

但仍然:角色只是具有特殊ROLE_前缀的权限。所以在 Spring 安全 3@PreAuthorize("hasRole('ROLE_XYZ')")@PreAuthorize("hasAuthority('ROLE_XYZ')")与 Spring 安全 4@PreAuthorize("hasRole('XYZ')")相同@PreAuthorize("hasAuthority('ROLE_XYZ')")

Regarding your use case:

关于您的用例:

Users have roles and roles can perform certain operations.

用户拥有角色,角色可以执行某些操作。

You could end up in GrantedAuthoritiesfor the roles a user belongs to and the operations a role can perform. The GrantedAuthoritiesfor the roles have the prefix ROLE_and the operations have the prefix OP_. An example for operation authorities could be OP_DELETE_ACCOUNT, OP_CREATE_USER, OP_RUN_BATCH_JOBetc. Roles can be ROLE_ADMIN, ROLE_USER, ROLE_OWNERetc.

您最终可能会GrantedAuthorities获得用户所属的角色以及角色可以执行的操作。在GrantedAuthorities对角色有前缀ROLE_和操作都有前缀OP_。一个例子为业务主管部门可能是OP_DELETE_ACCOUNTOP_CREATE_USEROP_RUN_BATCH_JOB等角色可以是ROLE_ADMINROLE_USERROLE_OWNER等。

You could end up having your entities implement GrantedAuthoritylike in this (pseudo-code) example:

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

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

    @ManyToMany
    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;

    @ManyToMany
    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;
    }
}

The ids of the roles and operations you create in your database would be the GrantedAuthority representation, e.g. ROLE_ADMIN, OP_DELETE_ACCOUNTetc. When a user is authenticated, make sure that all GrantedAuthorities of all its roles and the corresponding operations are returned from the UserDetails.getAuthorities() method.

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

Example: The admin role with id ROLE_ADMINhas the operations OP_DELETE_ACCOUNT, OP_READ_ACCOUNT, OP_RUN_BATCH_JOBassigned to it. The user role with id ROLE_USERhas the operation OP_READ_ACCOUNT.

例如:ID为admin角色ROLE_ADMIN有操作OP_DELETE_ACCOUNTOP_READ_ACCOUNTOP_RUN_BATCH_JOB分配给它。具有 id 的用户角色具有ROLE_USER操作OP_READ_ACCOUNT

If an admin logs in the resulting security context will have the GrantedAuthorities: ROLE_ADMIN, OP_DELETE_ACCOUNT, OP_READ_ACCOUNT, OP_RUN_BATCH_JOB

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

If a user logs it, it will have: ROLE_USER, OP_READ_ACCOUNT

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

The UserDetailsService would take care to collect all roles and all operations of those roles and make them available by the method getAuthorities() in the returned UserDetails instance.

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

回答by coder

AFAIK GrantedAuthority and roles are same in spring security. GrantedAuthority's getAuthority() string is the role (as per default implementation SimpleGrantedAuthority).

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

For your case may be you can use Hierarchical Roles

对于您的情况,您可以使用 Hierarchical Roles

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

Not the exact sol you looking for, but hope it helps

不是您正在寻找的确切溶胶,但希望它有所帮助

Edit: Reply to your comment

编辑:回复您的评论

Role is like a permission in spring-security. using intercept-url with hasRole provides a very fine grained control of what operation is allowed for which role/permission.

角色就像 spring-security 中的权限。将intercept-url 与hasRole 结合使用,可以非常精细地控制哪个角色/权限允许进行哪些操作。

The way we handle in our application is, we define permission (i.e. role) for each operation (or rest url) for e.g. view_account, delete_account, add_account etc. Then we create logical profiles for each user like admin, guest_user, normal_user. The profiles are just logical grouping of permissions, independent of spring-security. When a new user is added, a profile is assigned to it (having all permissible permissions). Now when ever user try to perform some action, permission/role for that action is checked against user grantedAuthorities.

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

Also the defaultn RoleVoter uses prefix ROLE_, so any authority starting with ROLE_ is considered as role, you can change this default behavior by using a custom RolePrefix in role voter and using it in spring security.

同样默认的 RoleVoter 使用前缀 ROLE_,因此任何以 ROLE_ 开头的权限都被视为角色,您可以通过在角色投票者中使用自定义 RolePrefix 并在 spring 安全中使用它来更改此默认行为。

回答by softjake

Another way to understand the relationship between these concepts is to interpret a ROLE as a container of Authorities.

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

Authorities are fine-grained permissions targeting a specific action coupled sometimes with specific data scope or context. For instance, Read, Write, Manage, can represent various levels of permissions to a given scope of information.

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

Also, authorities are enforced deep in the processing flow of a request while ROLE are filtered by request filter way before reaching the Controller. Best practices prescribe implementing the authorities enforcement past the Controller in the business layer.

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

On the other hand, ROLES are coarse grained representation of an set of permissions. A ROLE_READER would only have Read or View authority while a ROLE_EDITOR would have both Read and Write. Roles are mainly used for a first screening at the outskirt of the request processing such as http. ... .antMatcher(...).hasRole(ROLE_MANAGER)

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

The Authorities being enforced deep in the request's process flow allows a finer grained application of the permission. For instance, a user may have Read Write permission to first level a resource but only Read to a sub-resource. Having a ROLE_READER would restrain his right to edit the first level resource as he needs the Write permission to edit this resource but a @PreAuthorize interceptor could block his tentative to edit the sub-resource.

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

Jake

Hyman

回答by Jeremy

Like others have mentioned, I think of roles as containers for more granular permissions.

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

Although I found the Hierarchy Role implementation to be lacking fine control of these granular permission.
So I created a library to manage the relationships and inject the permissions as granted authorities in the security context.

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

I may have a set of permissions in the app, something like CREATE, READ, UPDATE, DELETE, that are then associated with the user's Role.

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

Or more specific permissions like READ_POST, READ_PUBLISHED_POST, CREATE_POST, PUBLISH_POST

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

These permissions are relatively static, but the relationship of roles to them may be dynamic.

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

Example -

例子 -

@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));
}

You may create APIs to manage the relationship of these permissions to a role.

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

I don't want to copy/paste another answer, so here's the link to a more complete explanation on SO.
https://stackoverflow.com/a/60251931/1308685

我不想复制/粘贴另一个答案,所以这里是关于 SO 的更完整解释的链接。
https://stackoverflow.com/a/60251931/1308685

To re-use my implementation, I created a repo. Please feel free to contribute!
https://github.com/savantly-net/spring-role-permissions

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