首页 > 解决方案 > 如何在 Spring Security 中允许任何其他角色?

问题描述

你将如何做一个表达式来允许访问所有角色,除非一个,而不在 spring-security.xml 中声明它们?

我们有四个角色:privateuser1和。是唯一可以执行某些服务的角色。其他只允许,和。user2user3privateuser1user2user3

<http pattern="/priv/**">
    <intercept-url pattern="/**" access="hasRole('private')"/>
    <http-basic/>
</http>

<http pattern="/pub/**">
    <intercept-url pattern="/**" access="!hasRole('private')"/>
    <http-basic/>
</http>

我知道有了这个,问题就解决了,但是在一个用户的情况下,private例如user2,这个用户应该可以执行/priv/and/pub/操作。如何配置xml?如果用户有两个角色(private以及其他角色中的一个),那么这两个操作都将被允许。

标签: xmlspringspring-security

解决方案


WebSecurityExpressionRoot您可以使用方法实现的扩展boolean hasAnyRoleExcept(String... ignoredRoles)


草图(在没有 IDE 支持的情况下编写)

import org.springframework.security.core.authority.AuthorityUtils;

public class MyWebSecurityExpressionRoot extends WebSecurityExpressionRoot {

   public MyWebSecurityExpressionRoot(final Authentication a, final FilterInvocation fi) {
      super(a, fi);
   }

   public boolean hasAnyRoleExcept(String... ignoredRoles) {
        //see SecurityExpressionRoot.hasAnyRole
        Set<String> roles = 
            AuthorityUtils.authorityListToSet(
               getAuthentication().getAuthorities());

        //find a not ignored role
        for (String role : roles) {
            if (!ignoredRoles.contains(role)) {
                return true;
            }
        }

        return false;
   }
}

要注册它:

public class MyWebSecurityExpressionHandler extends DefaultWebSecurityExpressionHandler {

    //Attention: override setTrustResolver too.
    private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

    @Override
    protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
        MyWebSecurityExpressionRoot root = new MyWebSecurityExpressionRoot(authentication, fi);
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(trustResolver);
        root.setRoleHierarchy(getRoleHierarchy());
        return root;
    }
}
<security:http use-expressions="true" ...>
    ...

    <security:expression-handler ref="myWebSecurityExpressionHandler"/>

    <security:intercept-url pattern="/**" access="hasAnyRoleExcept('private')"/>
</security:http>

<bean id="myWebSecurityExpressionHandler" class="MyWebSecurityExpressionHandler"/>

推荐阅读