Java 具有角色和权限的 Spring Security
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6357579/
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
Spring Security with roles and permissions
提问by flash
I'm trying to set up role-based Security with permissions. I'm trying to do this together with Spring-Security.
我正在尝试使用权限设置基于角色的安全性。我正在尝试与 Spring-Security 一起执行此操作。
I don't want to set up ACL as it seems it's an overkill for my requirements.
我不想设置 ACL,因为它似乎对我的要求来说太过分了。
I just want to have simple permissions and roles as described in this article. Unfortunately the article does not describe how to implement the given solution.
我只想拥有本文所述的简单权限和角色。不幸的是,这篇文章没有描述如何实现给定的解决方案。
Has someone already tried this and can point me in the right direction? Maybe there is another blog entry that describes the implementation?
有人已经尝试过这个并且可以指出我正确的方向吗?也许还有另一个博客条目描述了实现?
Thank you very much.
非常感谢。
采纳答案by ezequielb
To implement that, it seems that you have to:
要实现这一点,您似乎必须:
- Create your model (user, role, permissions) and a way to retrieve permissions for a given user;
- Define your own
org.springframework.security.authentication.ProviderManager
and configure it (set its providers) to a customorg.springframework.security.authentication.AuthenticationProvider
. This last one should return on its authenticate method a Authentication, which should be setted with theorg.springframework.security.core.GrantedAuthority
, in your case, all the permissions for the given user.
- 创建您的模型(用户、角色、权限)以及检索给定用户权限的方法;
- 定义您自己的
org.springframework.security.authentication.ProviderManager
并将其配置(设置其提供程序)为自定义org.springframework.security.authentication.AuthenticationProvider
. 最后一个应该在其身份验证方法上返回一个身份验证org.springframework.security.core.GrantedAuthority
,在您的情况下,它应该设置为给定用户的所有权限。
The trick in that article is to have roles assigned to users, but, to set the permissions for those roles in the Authentication.authorities
object.
那篇文章中的技巧是将角色分配给用户,但是,要为Authentication.authorities
对象中的这些角色设置权限。
For that I advise you to read the API, and see if you can extend some basic ProviderManager and AuthenticationProvider instead of implementing everything. I've done that with org.springframework.security.ldap.authentication.LdapAuthenticationProvider
setting a custom LdapAuthoritiesPopulator, that would retrieve the correct roles for the user.
为此,我建议您阅读 API,看看您是否可以扩展一些基本的 ProviderManager 和 AuthenticationProvider 而不是实现所有内容。我已经通过org.springframework.security.ldap.authentication.LdapAuthenticationProvider
设置自定义 LdapAuthoritiesPopulator来完成此操作,它将为用户检索正确的角色。
Hope this time I got what you are looking for. Good luck.
希望这次我得到了你要找的东西。祝你好运。
回答by gpeche
The basic steps are:
基本步骤是:
Use a custom authentication provider
<bean id="myAuthenticationProvider" class="myProviderImplementation" scope="singleton"> ... </bean>
Make your custom provider return a custom
UserDetails
implementation. ThisUserDetailsImpl
will have agetAuthorities()
like this:public Collection<GrantedAuthority> getAuthorities() { List<GrantedAuthority> permissions = new ArrayList<GrantedAuthority>(); for (GrantedAuthority role: roles) { permissions.addAll(getPermissionsIncludedInRole(role)); } return permissions; }
使用自定义身份验证提供程序
<bean id="myAuthenticationProvider" class="myProviderImplementation" scope="singleton"> ... </bean>
让您的自定义提供程序返回自定义
UserDetails
实现。这UserDetailsImpl
将有一个getAuthorities()
这样的:public Collection<GrantedAuthority> getAuthorities() { List<GrantedAuthority> permissions = new ArrayList<GrantedAuthority>(); for (GrantedAuthority role: roles) { permissions.addAll(getPermissionsIncludedInRole(role)); } return permissions; }
Of course from here you could apply a lot of optimizations/customizations for your specific requirements.
当然,从这里您可以针对您的特定要求应用大量优化/自定义。
回答by ezequielb
I'm the author of the article in question.
我是相关文章的作者。
No doubt there are multiple ways to do it, but the way I typically do it is to implement a custom UserDetails
that knows about roles and permissions. Role
and Permission
are just custom classes that you write. (Nothing fancy--Role
has a name and a set of Permission
instances, and Permission
has a name.) Then the getAuthorities()
returns GrantedAuthority
objects that look like this:
毫无疑问,有多种方法可以做到这一点,但我通常这样做的方法是实现一个UserDetails
了解角色和权限的自定义。Role
并且Permission
只是您编写的自定义类。(没什么特别的——Role
有一个名字和一组Permission
实例,Permission
还有一个名字。)然后getAuthorities()
返回的GrantedAuthority
对象看起来像这样:
PERM_CREATE_POST
, PERM_UPDATE_POST
, PERM_READ_POST
PERM_CREATE_POST
, PERM_UPDATE_POST
,PERM_READ_POST
instead of returning things like
而不是返回诸如
ROLE_USER
, ROLE_MODERATOR
ROLE_USER
, ROLE_MODERATOR
The roles are still available if your UserDetails
implementation has a getRoles()
method. (I recommend having one.)
如果您的UserDetails
实现有getRoles()
方法,角色仍然可用。(我建议有一个。)
Ideally you assign roles to the user and the associated permissions are filled in automatically. This would involve having a custom UserDetailsService
that knows how to perform that mapping, and all it has to do is source the mapping from the database. (See the article for the schema.)
理想情况下,您为用户分配角色,并自动填写相关的权限。这将涉及拥有一个UserDetailsService
知道如何执行该映射的自定义,并且它所要做的就是从数据库中获取映射。(有关架构,请参阅文章。)
Then you can define your authorization rules in terms of permissions instead of roles.
然后,您可以根据权限而不是角色来定义您的授权规则。
Hope that helps.
希望有帮助。
回答by Neil McGuigan
This is the simplest way to do it. Allows for group authorities, as well as user authorities.
这是最简单的方法。允许组权限以及用户权限。
-- Postgres syntax
create table users (
user_id serial primary key,
enabled boolean not null default true,
password text not null,
username citext not null unique
);
create index on users (username);
create table groups (
group_id serial primary key,
name citext not null unique
);
create table authorities (
authority_id serial primary key,
authority citext not null unique
);
create table user_authorities (
user_id int references users,
authority_id int references authorities,
primary key (user_id, authority_id)
);
create table group_users (
group_id int references groups,
user_id int referenecs users,
primary key (group_id, user_id)
);
create table group_authorities (
group_id int references groups,
authority_id int references authorities,
primary key (group_id, authority_id)
);
Then in META-INF/applicationContext-security.xml
然后在 META-INF/applicationContext-security.xml
<beans:bean class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" id="passwordEncoder" />
<authentication-manager>
<authentication-provider>
<jdbc-user-service
data-source-ref="dataSource"
users-by-username-query="select username, password, enabled from users where username=?"
authorities-by-username-query="select users.username, authorities.authority from users join user_authorities using(user_id) join authorities using(authority_id) where users.username=?"
group-authorities-by-username-query="select groups.id, groups.name, authorities.authority from users join group_users using(user_id) join groups using(group_id) join group_authorities using(group_id) join authorities using(authority_id) where users.username=?"
/>
<password-encoder ref="passwordEncoder" />
</authentication-provider>
</authentication-manager>
回答by Alexander Pilch
Just for sake of completeness (maybe someone else won't have to implement it from scratch):
只是为了完整起见(也许其他人不必从头开始实现它):
We've implemented our own small library, as everyone else. It's supposed to make things easier, so that our developers don't have to reimplement it each time. It would be great if spring security would provide support of rbac out of the box, as this approach is much better than the default permission based one.
和其他人一样,我们已经实现了我们自己的小型图书馆。它应该让事情变得更容易,这样我们的开发人员就不必每次都重新实现它。如果 spring security 能够提供开箱即用的 rbac 支持那就太好了,因为这种方法比基于默认权限的方法要好得多。
Have a look at Github(OSS, MIT license) to see if it suits your needs. It's basically only addressing the role <-> privileges mapping. The missing piece, you'll have to provide on your own is basically the user <-> roles mapping, e.g. by mapping groups (racf/ad groups) to roles (1:1) or by implementing an additional mapping. That one's different in each project, so it doesn't make sense to provide some implementation.
看看Github(OSS,MIT 许可证),看看它是否适合您的需求。它基本上只解决角色 <-> 权限映射。您必须自己提供的缺失部分基本上是用户 <-> 角色映射,例如通过将组(racf/ad 组)映射到角色 (1:1) 或通过实施附加映射。那个在每个项目中都不一样,所以提供一些实现是没有意义的。
We've basically used this internally, so that we can start with rbac from the beginning. We can still replace it with some other implementation later on, if the application is growing, but it's important for us to get the setup right at the beginning.
我们基本上已经在内部使用了它,因此我们可以从一开始就使用 rbac。如果应用程序不断增长,我们仍然可以稍后用其他一些实现替换它,但对我们来说在开始时正确设置很重要。
If you don't use rbac, there's a good chance, that the permissions are scattered throughout the codebase and you'll have a hard time to extract/group those (into roles) later on. The generated graphs do also help to reason about it/restructure it later on.
如果您不使用 rbac,则权限很可能分散在整个代码库中,稍后您将很难将它们提取/分组(到角色中)。生成的图也有助于稍后对其进行推理/重组。
回答by Jeremy
ACL was overkill for my requirements also.
I ended up creating a library similar to @Alexander's to inject a GrantedAuthority
list for Role->Permissions based on the role membership of a user.
ACL 对我的要求也太过分了。
我最终创建了一个类似于@Alexander 的库,以GrantedAuthority
根据用户的角色成员身份为 Role->Permissions注入一个列表。
For example, using a DB to hold the relationships -
例如,使用数据库来保存关系 -
@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));
}
When an Authentication object is injected in the current security session, it will have the original roles/granted authorities.
在当前安全会话中注入 Authentication 对象时,它将具有原始角色/授予的权限。
This library provides 2 built-in integration points for Spring Security.
When the integration point is reached, the PermissionProvider is called to get the effective permissions for each role the user is a member of.
The distinct list of permissions are added as GrantedAuthority items in the Authentication object.
这个库为 Spring Security 提供了 2 个内置的集成点。当到达集成点时,将调用 PermissionProvider 以获取用户所属的每个角色的有效权限。
不同的权限列表被添加为 Authentication 对象中的 GrantedAuthority 项目。
You can also implement a custom PermissionProvider
to store the relationships in config for example.
例如,您还可以实现自定义PermissionProvider
以将关系存储在配置中。
A more complete explanation here - https://stackoverflow.com/a/60251931/1308685
更完整的解释在这里 - https://stackoverflow.com/a/60251931/1308685
And the source code is here - https://github.com/savantly-net/spring-role-permissions
源代码在这里 - https://github.com/savantly-net/spring-role-permissions