10 Spring Security 之 voter

Spring Security Voter 鉴权

Spring Security中,系统进行认证以后,获得了当前的Authorities,紧接着,Spring Security会进行鉴权,判断他是否有权限。

这个判断主要通过投票管理器+投票器实现。

投票器实现某一个条件的权限判断,投票管理器设置策略,对多个投票器的判断结果进行综合。

整个认证鉴权的代码流程图,如下:

spring security

websecurity

首先,我们修改一下WebSecurityConfig

package com.it_laowu.springbootstudy.springbootstudydemo.core.config;
......
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
......
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.httpBasic().and().authorizeRequests() .accessDecisionManager(accessDecisionManager())
        ......
     }

    private AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> decisionVoters = Arrays.asList(new WebExpressionVoter(),new DataVoter() );
        // return new MyDecisionManagerAffirmative(decisionVoters);
        return new MyDecisionManagerUnanimous(decisionVoters);
    }
}

这样,我们就把自己定义的投票器管理器MyDecisionManagerUnanimous和两个投票器WebExpressionVoter DataVoter注册到了SpringSecurity。投票管理器分析投票器的返回结果,并通过你定义的策略,决定最终的投票结果。比如:MyDecisionManagerUnanimous是一票反对,MyDecisionManagerAffirmative是一票通过。

投票管理器

自己创建MyDecisionManagerAffirmative MyDecisionManagerUnanimous,代码基本来自AffirmativeBased UnanimousBased

投票器

WebExpressionVoter会对当前url进行分析,符合WebSecurityConfig中的自定义权限就返回ACCESS_GRANTED。也可以将WebSecurityConfig中的权限定义存放到数据库中,然后重写一个WebExpressionVoter,进行分析,我这里就省略了。

我们新增了DataVoter的分析,即数据权限的分析。这里仅仅举个例子,就是用户admin2有权限。

//DataVoter
package com.it_laowu.springbootstudy.springbootstudydemo.core.auth;
......
public class DataVoter implements AccessDecisionVoter<Object> {
    private static final Logger logger = LoggerFactory.getLogger(DataVoter.class);
    @Override
    public boolean supports(ConfigAttribute attribute) {
        return true;
    }
    @Override
    public boolean supports(Class<?> clazz) {
        return true;
    }
    @Override
    public int vote(Authentication authentication, Object object, Collection<ConfigAttribute> attributes) {
        if (authentication == null) {
            return ACCESS_DENIED;
        }
        //判断是否匿名用户,是的话不判断权限
        Boolean anoymouse = authentication.getAuthorities().stream()
            .anyMatch(i->{return i.toString()=="ROLE_ANONYMOUS";});
        if (anoymouse){
            return ACCESS_GRANTED;
        }
        //如果是需要验证的页面,只有用户admin2有权限(原谅我的粗糙)
        String username = authentication.getName();
        if (StrUtil.startWith(username, "admin2", true)) {
            return ACCESS_GRANTED;
        }
        for (ConfigAttribute attribute : attributes) {
            System.out.println("attribute:"+attribute);
        }
        logger.debug("username:"+username);
        for (ConfigAttribute attribute : attributes) {
            logger.debug("attribute:"+attribute);
            for (GrantedAuthority auth : authentication.getAuthorities()) {
                logger.debug("auth:"+auth);
                if (attribute.getAttribute().trim().equals(auth.getAuthority().trim())) {
                    return ACCESS_GRANTED;
                }
            }
        }
        return ACCESS_ABSTAIN;
    }
}

完毕。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容