【问题标题】:Implementing Hierarchical Roles in Spring Security在 Spring Security 中实现分层角色
【发布时间】:2014-05-01 21:44:16
【问题描述】:

我正在尝试在 Spring 安全性中实现分层角色,并根据 spring 源文档在我的 xml 文件中添加以下配置。

<bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
    <property name="hierarchy">
        <value>
            ROLE_ADMIN > ROLE_PRO
            ROLE_PRO > ROLE_PREMIUM
            ROLE_PREMIUM > ROLE_BASIC
            ROLE_BASIC > ROLE_ANONYMOUS
        </value>
    </property>
</bean>

 <bean id="roleVoter"
        class="org.springframework.security.access.vote.RoleHierarchyVoter">
         <constructor-arg ref="roleHierarchy"/>
</bean>

我已经尝试过以上几行,但是当 ROLE_ADMIN 尝试访问分配给 ROLE_BASIC 的 url 时,我得到了拒绝访问。除了这个,我还需要添加什么吗?除了 Spring 站点中的那些行,我什么也没找到。另外,如果您知道分层角色的任何良好实现,请务必提及。

【问题讨论】:

    标签: spring spring-security acl


    【解决方案1】:

    我认为您需要在accessDecisionManager 注册roleVoter。 @参见this answer 示例。


    但老实说,我doubt the Spring Hierarchical Voter concept,因为你需要在任何地方添加一个特殊的分层投票者。我个人更喜欢另一种方式:我实现了一个自定义JdbcDaoImpl,它覆盖了addCustomAuthorities,并将“普通”角色添加到“现有”角色一次。

    /**
     * Extension of {@link JdbcDaoImpl} User Detail Provider, so that is uses the
     * {@link PrivilegesService} to extend the provided Authorities.
     *
     */
    public class JdbcDaoPrivilegesImpl extends JdbcDaoImpl {
    
        private PrivilegesService privilegesService;
    
        public JdbcDaoPrivilegesImpl(final PrivilegesService privilegesService) {        
            this.privilegesService = privilegesService;
        }
    
        @Override
        protected void addCustomAuthorities(String username, List<GrantedAuthority> authorities) {
            super.addCustomAuthorities(username, authorities);         
    
            List<GrantedAuthority> privileges = new ArrayList<GrantedAuthority>();
            for (GrantedAuthority role : authorities) {
                privileges.addAll(privilegesService.getPrivilegesForRole(role));
            }
            authorities.addAll(privileges);    
        }
    }
    
    
    public interface PrivilegesService {
    
         Collection<? extends GrantedAuthority> getPrivilegesForRole(GrantedAuthority role);
    }
    
    
    public class PropertyPrivilegesServiceImpl implements PrivilegesService {
    
        /**
         * Property bases mapping of roles to privileges.
         * Every role is one line, the privileges are comma separated.
         */
        private Properties roleToPrivileges;
    
        public PropertyPrivilegesServiceImpl(Properties roleToPrivileges) {
            if (roleToPrivileges == null) {
                throw new IllegalArgumentException("roleToPrivileges must not be null");
            }
            this.roleToPrivileges = roleToPrivileges;
        }
    
        @Override
        public Collection<? extends GrantedAuthority> getPrivilegesForRole(GrantedAuthority role) {
            if (roleToPrivileges == null) {
                throw new IllegalArgumentException("role must not be null");
            }
    
            String authority = role.getAuthority();
            if(authority != null) {
                String commaSeparatedPrivileges = roleToPrivileges.getProperty(role.getAuthority());
                if (commaSeparatedPrivileges != null) {
                    List<GrantedAuthority> privileges = new ArrayList<GrantedAuthority>();
                    for(String privilegeName : StringUtils.commaDelimitedListToSet(commaSeparatedPrivileges)) {
                        privileges.add(new GrantedAuthorityImpl(privilegeName.trim()));
                    }                
                    return privileges;
                } else {
                    return Collections.emptyList();
                }
            } else {
                return Collections.emptyList();
            }
        }
    }
    

    示例配置

      <bean id="myUserDetailsService" class="JdbcDaoForUpdatableUsernames">
        <constructor-arg ref="propertyPrivilegesService"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="usersByUsernameQuery" value="SELECT login,encryptedPassword,loginEnabled FROM user WHERE login = ?"/>
        <property name="enableAuthorities" value="true"/>
        <property name="authoritiesByUsernameQuery" value="SELECT u.login, r.securityRoles FROM user u, user2security_roles r WHERE u.login= ? AND u.id = r. User_fk;"/>
    </bean>
    
     <bean id="propertyPrivilegesService" class="PropertyPrivilegesServiceImpl">
        <constructor-arg>
            <props>
                <prop key="ROLE_ADMIN">
                    ROLE_PREMIUM,
                    ROLE_BASIC
                </prop>
                <prop key="ROLE_PREMIUM">
                    RROLE_BASIC
                </prop>
            </props>
        </constructor-arg>
    </bean>
    

    【讨论】:

    • @carlspring:没有可用的公开示例。 (所有你需要在这个答案中实现这一点)。 -- 名称:我将其命名为“Role-Privilege-Approach”,但这不是正式名称。
    【解决方案2】:

    尝试将其添加到 spring-security.xml

    <http auto-config="true" use-expressions="true" access-decision-manager-ref="accessDecisionManager">
    
    
    <beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
        <beans:constructor-arg>
            <beans:list>
                <beans:ref bean="roleVoter" />
            </beans:list>
        </beans:constructor-arg>
    </beans:bean>
    

    【讨论】:

      猜你喜欢
      • 2014-12-26
      • 2019-12-19
      • 1970-01-01
      • 2018-07-28
      • 2019-02-13
      • 1970-01-01
      • 2019-06-21
      • 2016-01-03
      • 2012-12-01
      相关资源
      最近更新 更多