具有角色和权限的Spring Security


77

我正在尝试设置具有权限的基于角色的安全性。我正在尝试与Spring-Security一起执行此操作。

我不想设置ACL,因为这似乎对我的要求来说太过严格了。

我只想拥有本文所述的简单权限和角色。不幸的是,本文没有描述如何实现给定的解决方案。

有人已经尝试过了,可以指出正确的方向吗?也许还有另一个博客条目描述了实现方式?

非常感谢你。


15
对于所有到达这里的人,都有一篇文章可以完全解决我的问题。请看看这个
闪光

我读了这篇文章,而林正试图实现这一点。您能告诉我您是如何实现SpringSecurityDaoImpl类的吗?@PreAuthorize根本不影响我的网址!我做的和文章中的内容完全一样。
新浪2014年

@sina您不必像示例中那样实现SpringSecurityDaoImpljust扩展JdbcDaoImpl。确保查看github上的示例代码,本文中引用了该示例代码。
闪光

Answers:


32

要实现这一点,您似乎必须:

  1. 创建模型(用户,角色,权限)以及检索给定用户权限的方法;
  2. 定义自己的 org.springframework.security.authentication.ProviderManager并将其配置(设置其提供程序)为custom org.springframework.security.authentication.AuthenticationProvider。最后一个应该在其authenticate方法上返回Authentication,对于org.springframework.security.core.GrantedAuthority您的情况,应该使用来设置给定用户的所有权限。

该文章中的技巧是为用户分配角色,但是要为Authentication.authorities对象中的这些角色设置权限。

为此,我建议您阅读API,并查看是否可以扩展一些基本的ProviderManager和AuthenticationProvider而不是全部实现。我通过org.springframework.security.ldap.authentication.LdapAuthenticationProvider设置自定义LdapAuthoritiesPopulator完成了此任务,该操作将为用户检索正确的角色。

希望这次我能得到您想要的。祝好运。


1
扩展此DaoAuthenticationProvider并为其提供一个自定义UserDetailsS​​ervice,以执行权限加载。
ezequielb 2011年

78

我是有关文章的作者。

毫无疑问,有多种方法可以执行此操作,但是我通常的方法是实现一个UserDetails了解角色和权限的自定义。Role并且Permission是你写的只是自定义类。(没有花哨的东西-Role有一个名称和一组Permission实例,并Permission有一个名称。)然后getAuthorities()返回如下所示的GrantedAuthority对象:

PERM_CREATE_POSTPERM_UPDATE_POSTPERM_READ_POST

而不是返回诸如

ROLE_USERROLE_MODERATOR

如果您的UserDetails实现具有getRoles()方法,则角色仍然可用。(我建议有一个。)

理想情况下,您将角色分配给用户,并且关联的权限会自动填写。这将涉及拥有一个UserDetailsService知道如何执行该映射的自定义,而它所要做的就是从数据库中获取映射。(有关架构,请参见文章。)

然后,您可以根据权限而不是角色来定义授权规则。

希望能有所帮助。


1
嗨,能否请您提供该答案中详细说明的“自定义用户”详细信息的实用解决方案?谢谢。
rayman 2013年

嗨,我使用自定义AuthenticationProvider和UserDetailsS​​ervice类使用Spring Security实现了一个应用程序。现在,我想在应用程序中使用角色和权限。我现在使用的是:@Secured(“ ROLE_ADMIN”),它仅使用角色。我如何扩展它来处理权限。(更多详细信息在这里-> stackoverflow.com/questions/23072619/…
Kleber Mota

6

基本步骤是:

  1. 使用自定义身份验证提供程序

    <bean id="myAuthenticationProvider" class="myProviderImplementation" scope="singleton">
    ...
    </bean>
    

  2. 使您的自定义提供程序返回自定义UserDetails实现。这UserDetailsImpl将是getAuthorities()这样的:

    public Collection<GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> permissions = new ArrayList<GrantedAuthority>();
        for (GrantedAuthority role: roles) {
            permissions.addAll(getPermissionsIncludedInRole(role));
        }
        return permissions;
    }
    

当然,从这里开始,您可以针对您的特定要求进行很多优化/自定义。


5

这是最简单的方法。允许组权限以及用户权限。

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

然后在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>

1

仅出于完整性考虑(也许其他人不必从头开始实现它):

和其他所有人一样,我们已经实现了自己的小型图书馆。它应该使事情变得容易,以便我们的开发人员不必每次都重新实现它。如果Spring Security可以提供现成的rbac支持,那就太好了,因为这种方法比基于默认权限的方法好得多。

查看Github(OSS,MIT许可证),看看它是否适合您的需求。基本上,它仅解决角色<->特权映射。您必须自己提供的缺失部分基本上是用户<->角色映射,例如,通过将组(racf / ad组)映射到角色(1:1)或通过实现其他映射。每个项目都不同,因此提供一些实现没有任何意义。

我们基本上在内部使用了它,因此我们可以从一开始就使用rbac。如果应用程序正在增长,我们以后仍然可以用其他一些实现方式替换它,但是对我们来说,从一开始就正确进行设置很重要。

如果您不使用rbac,则很有可能将权限分散在整个代码库中,并且以后将很难提取(或将它们组合到角色中)。生成的图形也确实有助于推理/稍后重新构造它。


1

对于我的要求,ACL也是过大的。
我最终创建了一个类似于@Alexander的库,以GrantedAuthority根据用户的角色成员资格为Role-> Permissions注入一个列表。

例如,使用DB来保存关系-

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

在当前安全会话中注入身份验证对象时,它将具有原始角色/授予的权限。

该库为Spring Security提供了2个内置的集成点。达到集成点时,将调用PermissionProvider以获得用户所属的每个角色的有效权限。
权限的不同列表添加为Authentication对象中的GrantedAuthority项目。

例如,您也可以实现自定义PermissionProvider以将关系存储在config中。

此处更完整的解释-https: //stackoverflow.com/a/60251931/1308685

源代码在这里 -https://github.com/savantly-net/spring-role-permissions


0

阅读完这篇文章后,来自Baeldung。我发现解决方案非常简单。

我所做的就是将角色和权限添加到GrantedAuthority中。我可以访问hasRole()和hasAuthority()这两种方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.