将RoleHierarchy应用于客户端角色

时间:2018-04-17 12:56:56

标签: spring-security spring-security-oauth2

对于我的应用程序中的安全角色,我们定义了一个RoleHierarchy,但是当我们尝试使用@PreAuthorize("#oauth2.clientHasRole('somerole')")检查客户端角色时,我们默认通知我们的Hirarchy不适用于客户端角色。

除了在OAuth2MethodSecurityExpressionHandler

上设置roleHierarchy之外,还需要一些额外的配置吗?

1 个答案:

答案 0 :(得分:0)

正常OAuth2MethodSecurityExpressionHandler不会将RoleHierarchy应用于客户端 - 权限。为了解决这个问题,我通过扩展它来添加我自己的ExpressionHandler。

public class HierarchicalOAuth2MethodSecurityExpressionHandler extends OAuth2MethodSecurityExpressionHandler {
    public HierarchicalOAuth2MethodSecurityExpressionHandler() {
        super();
    }

    @Override
    public StandardEvaluationContext createEvaluationContextInternal(Authentication authentication, MethodInvocation mi) {
        StandardEvaluationContext ec = super.createEvaluationContextInternal(authentication, mi);
        ec.setVariable("oauth2roles", new HierarchicalOAuth2SecurityExpressionMethods(authentication, getRoleHierarchy()));
        return ec;
    }
}

public class HierarchicalOAuth2SecurityExpressionMethods extends OAuth2SecurityExpressionMethods {

    private RoleHierarchy roleHierarchy;
    private Authentication authentication;

    public HierarchicalOAuth2SecurityExpressionMethods(Authentication authentication, RoleHierarchy roleHierarchy) {
        super(authentication);
        this.authentication = authentication;
        this.roleHierarchy = roleHierarchy;
    }

    @Override
    public boolean clientHasAnyRole(String... roles) {
        if (authentication instanceof OAuth2Authentication) {
            OAuth2Request clientAuthentication = ((OAuth2Authentication) authentication).getOAuth2Request();
            Collection<? extends GrantedAuthority> clientAuthorities = roleHierarchy.getReachableGrantedAuthorities(clientAuthentication.getAuthorities());
            if (clientAuthorities != null) {
                Set<String> roleSet = AuthorityUtils.authorityListToSet(clientAuthorities);
                for (String role : roles) {
                    if (roleSet.contains(role)) {
                        return true;
                    }
                }
            }
        }

        return false;
    }
}

现在,如果需要,我可以选择使用#oauth2roles.clientHasAnyRole(...)。