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
Difference between Role and GrantedAuthority in Spring Security
提问by Chinmay
There are concepts and implementations in Spring Security, such as the GrantedAuthority
interface 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
).
我希望允许的操作,例如createSubUsers或deleteAccounts,我会允许管理员(具有角色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 hasRole
consuming a GrantedAuthority
string? 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.UserDetails
interface 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(权限)。您通常通过实现自己的 UserDetailsService 来实现,该服务返回 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 hasRole
expression 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,角色的处理更加一致,处理“角色”(如RoleVoter
、hasRole
表达式等)的代码总是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 GrantedAuthorities
for the roles a user belongs to and the operations a role can perform. The GrantedAuthorities
for 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_JOB
etc. Roles can be ROLE_ADMIN
, ROLE_USER
, ROLE_OWNER
etc.
您最终可能会GrantedAuthorities
获得用户所属的角色以及角色可以执行的操作。在GrantedAuthorities
对角色有前缀ROLE_
和操作都有前缀OP_
。一个例子为业务主管部门可能是OP_DELETE_ACCOUNT
,OP_CREATE_USER
,OP_RUN_BATCH_JOB
等角色可以是ROLE_ADMIN
,ROLE_USER
,ROLE_OWNER
等。
You could end up having your entities implement GrantedAuthority
like 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_ACCOUNT
etc. 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_ADMIN
,OP_DELETE_ACCOUNT
等。当用户通过身份验证时,请确保其所有角色的所有 GrantedAuthorities 和相应操作都从 UserDetails.getAuthorities() 返回方法。
Example:
The admin role with id ROLE_ADMIN
has the operations OP_DELETE_ACCOUNT
, OP_READ_ACCOUNT
, OP_RUN_BATCH_JOB
assigned to it.
The user role with id ROLE_USER
has the operation OP_READ_ACCOUNT
.
例如:ID为admin角色ROLE_ADMIN
有操作OP_DELETE_ACCOUNT
,OP_READ_ACCOUNT
,OP_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.
UserDetailsService 将负责收集所有角色和这些角色的所有操作,并通过返回的 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