在 Spring Security 中实现分层角色
Posted
技术标签:
【中文标题】在 Spring Security 中实现分层角色【英文标题】:Implementing Hierarchical Roles in 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 站点中的那些行,我什么也没找到。另外,如果您知道分层角色的任何良好实现,请务必提及。
【问题讨论】:
【参考方案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>
【讨论】:
以上是关于在 Spring Security 中实现分层角色的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Security 中实现基于 JWT 的身份验证和授权
在 Spring Security 2.06 中实现自定义 AuthenticationProvider