【问题标题】:Spring Security with roles and permissions具有角色和权限的 Spring Security
【发布时间】:2011-09-15 12:01:01
【问题描述】:

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

我不想设置 ACL,因为这对我的要求来说似乎有点过头了。

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

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

非常感谢。

【问题讨论】:

  • 对于所有来到这里的人,有一篇文章正好解决了我的问题。请看this
  • 我读过那篇文章并试图实现它。你能告诉我你是如何实现那个 SpringSecurityDaoImpl 类的吗? @PreAuthorize 根本不会影响我的网址!我所做的与那篇文章中的材料完全一样。
  • @sina 您不必实现SpringSecurityDaoImpl,只需扩展JdbcDaoImpl,就像在示例中一样。请务必查看github上的示例代码,文章中引用了该示例代码。

标签: java spring-security


【解决方案1】:

我是相关文章的作者。

毫无疑问,有多种方法可以做到这一点,但我通常这样做的方法是实现一个知道角色和权限的自定义UserDetailsRolePermission 只是您编写的自定义类。 (没什么特别的——Role 有一个名称和一组Permission 实例,Permission 有一个名称。)然后getAuthorities() 返回GrantedAuthority 看起来像这样的对象:

PERM_CREATE_POSTPERM_UPDATE_POSTPERM_READ_POST

而不是返回类似的东西

ROLE_USER, ROLE_MODERATOR

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

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

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

希望对您有所帮助。

【讨论】:

  • 嗨,您能否提供一个实用的自定义用户详细信息解决方案,如您在该答案中详述的那样?谢谢。
  • 嗨,我使用 Spring Security 使用自定义 AuthenticationProvider 和 UserDetailsS​​ervice 类实现了一个应用程序。现在,我想在我的应用程序中使用角色和权限。我现在使用这个:@Secured("ROLE_ADMIN"),它只使用处理角色。我如何扩展它来处理权限。 (更多细节在这里 -> stackoverflow.com/questions/23072619/…
【解决方案2】:

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

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

那篇文章中的技巧是将角色分配给用户,但是,在Authentication.authorities 对象中设置这些角色的权限。

为此,我建议您阅读 API,看看您是否可以扩展一些基本的 ProviderManager 和 AuthenticationProvider 而不是实现所有内容。我已经通过 org.springframework.security.ldap.authentication.LdapAuthenticationProvider 设置了一个自定义 LdapAuthoritiesPopulator 来做到这一点,这将为用户检索正确的角色。

希望这次我得到了你想要的东西。 祝你好运。

【讨论】:

  • 扩展这个 DaoAuthenticationProvider 并给它一个自定义的 UserDetailsS​​ervice,它应该执行权限加载。
【解决方案3】:

基本步骤是:

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

当然,您可以从这里针对您的特定要求应用大量优化/自定义。

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 能否请您添加关于表格的简单数据?
    【解决方案5】:

    只是为了完整起见(也许其他人不必从头开始实现它):

    和其他人一样,我们已经实现了自己的小型库。它应该让事情变得更容易,这样我们的开发人员就不必每次都重新实现它。如果 spring security 能够开箱即用地提供对 rbac 的支持,那就太好了,因为这种方法比基于默认权限的方法要好得多。

    查看Github(OSS,MIT 许可证),看看它是否适合您的需求。它基本上只是解决角色 权限映射。缺少的部分,您必须自己提供基本上是用户 角色映射,例如通过将组(racf/ad 组)映射到角色 (1:1) 或实施附加映射。这个在每个项目中都不一样,所以提供一些实现是没有意义的。

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

    如果您不使用 rbac,则很有可能权限分散在整个代码库中,您以后将很难将这些权限提取/分组(到角色中)。 生成的图表也有助于稍后对其进行推理/重组。

    【讨论】:

      【解决方案6】:

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

      例如,使用数据库来保存关系 -

      @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 以获取用户所属的每个角色的有效权限。
      不同的权限列表作为 GrantedAuthority 项添加到 Authentication 对象中。

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

      这里有更完整的解释-https://stackoverflow.com/a/60251931/1308685

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

      【讨论】:

        【解决方案7】:

        在阅读了来自 Baeldung 的 post 之后。我发现解决方案很简单。

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

        【讨论】:

          猜你喜欢
          • 2018-12-30
          • 2011-12-24
          • 2022-08-09
          • 1970-01-01
          • 2012-10-24
          • 2020-06-01
          • 2016-02-27
          • 2013-05-17
          • 2012-01-09
          相关资源
          最近更新 更多