Spring Security(六):授权体系

授权体系

  • Spring Security 授权介绍
    • Spring Security使用AccessDecisionManager来鉴定当前用户是否有访问对应受保护对象的权限
      在这里插入图片描述
  • AccessDecisionManager 接口
public interface AccessDecisionManager {
	/**
	 * Resolves an access control decision for the passed parameters.
	 * 认证过的票据Authentication,确定了谁正在访问资源
	 * @param authentication the caller invoking the method (not null)
	 * 被访问的资源object
	 * @param object the secured object being called
	 * 访问资源要求的权限配置ConfigAttributeDefinition
	 * @param configAttributes the configuration attributes associated with the secured
	 * object being invoked
	 * 从票据中可以获取认证用户所拥有的权限,再对比访问资源要求的权限,即可断定当前认证用户是否能够访问该资源
	 */
	void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException,InsufficientAuthenticationException;
	
	boolean supports(ConfigAttribute attribute);
	
	boolean supports(Class<?> clazz);
	
}
  • AccessDecisionVoter 接口
    • Spring Security引入了投票器的概念,真正的授权功能是通过一组AccessDecisionVoter来实现的
    • AccessDecisionManager维护着一个AccessDecisionVoter列表参与授权的投票。根据处理投票的策略不同,Spring Security中AccessDecisionManager有3个不同的实现
      • UnanimousBased(全票通过):所有投票器都通过才允许访问资源
      • ConsensusBased(少数服从多数):超过一半的投票器通过才允许访问资源
      • AffirmativeBased(一票通过):只要有一个投票器投票通过,就允许访问资源
    • AccessDecisionVoter的vote方法,实现了投票的逻辑,vote方法需要的参数和AccessDecisionManager的decide方法相同,实际上AccessDecisionManager的功能就是委托给AccessDecisionVoter实现
    • Spring Security中有很多AccessDecisionVoter的实现,最简单的有RoleVoter。RoleVoter通过将Authentication里面获取的权限信息,与从
      ConfigAttributeDefinition配置的访问资源需要的权限对比,来投票通过,或拒绝,或弃权

授权案例

  • 自定义AccessDecisionManager
public class MyAccessDecisionManager implements AccessDecisionManager {
    
    private static final Logger logger = LoggerFactory.getLogger(MyAccessDecisionManager.class);
    private Map<String, List<String>> map = new HashMap<>();
    public MyAccessDecisionManager() {
        //登陆用户-访问地址映射表
        map.put("zhangsan", Arrays.asList("/index", "/home", "/ok"));
        map.put("admin", Arrays.asList("/index", "/home", "/admin","/ok"));
    }
     /**
     * 如果验证不通过,则需要抛出AccessDeniedException异常
     * <p>
     * 和登陆有关的url必须要通过验证,否则会陷入死循环
     */
     @Override
    public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
            throws AccessDeniedException, InsufficientAuthenticationException {

        logger.info(" * * * * * * * * decide  * * * * * * * * ");
        logger.info("authentication: " + authentication);
        logger.info("object: " + object);
        logger.info("configAttributes: " + configAttributes);

        FilterInvocation fi = (FilterInvocation) object;
        String url = fi.getHttpRequest().getRequestURI();
        if (url.endsWith(".html") || url.endsWith(".htm") || url.endsWith(".css") || url.endsWith(".js")) {
            //静态页面不用校验
            return;
        } else if ("/loginHome".equals(url) || "/loginFail".equals(url) || "/doLogin".equals(url)) {
            //登陆地址用校验
            return;
        }
        String user = authentication.getName();
		logger.info("user: " + user);
        List<String> list = map.get(user);
        if (list == null || list.isEmpty()) {
            throw new AccessDeniedException("无此权限");
        }
        for (String attr : list) {
            if (url.equals(attr)) {
                return;
            }
        }
        throw new AccessDeniedException("无此权限");
    }
    @Override
    public boolean supports(ConfigAttribute attribute) {
		logger.info(" * * * * * * * * supports(ConfigAttribute attribute) : " + attribute);
        return true;
    }
    @Override
    public boolean supports(Class<?> clazz) {
		logger.info(" * * * * * * * * supports(Class<?> clazz) : " + clazz);
        return FilterInvocation.class.equals(clazz);
    }
}
  • 将自定义MyAccessDecisionManager 加入WebSecurityConfig
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	http.authorizeRequests().anyRequest().authenticated();
    	//添加自定义MyAccessDecisionManager 
    	http.authorizeRequests().accessDecisionManager(new MyAccessDecisionManager());
    	http.formLogin();
    	http.logout();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值