第九期 AccessDecisionManager组件介绍

作为访问控制的最后一期,但确实整个章节部分里最简单的一部分。ConfigAttribute负责表述规则,AccessDecisionVoter负责为规则表决,但最终的访问授权是否通过是由AccessDecisionManager进行决策的。 这一期我们将主要介绍Spring Security中提供的三种主要决策模型。

一、AccessDecisionManager接口说明

AccessDecisionManager的接口表述非常的简单,简单来说就一个主要功——为当前的访问规则进行决策,是否给予访问的权限。无论是decide方法还是supports方法,AccessDecisionManager本身并不完成相关的逻辑,全部交由其管理的AccessDecisionVoter依次去判断与执行。而根据decide的逻辑规则不同,Spring Security中分别存在三种不同decide决策规则的AccessDecisionManager,它们分别是:

  • AffirmativeBased
  • UnanimousBased
  • ConsensusBased 在Spring Security默认设置中,使用的是AffirmativeBased

在详细介绍三种AccessDecisionManager的实现类前,我们先再来梳理下AccessDecisionManagerAccessDecisionVoter的在决策框架中的关系。 在框架设计中AccessDecisionManagerAccessDecisionVoter的集合类,管理着对于不同规则进行判断与表决的AccessDecisionVoter们。 但不同的是,AccessDecisionVoter分别都只会对自己支持的规则进行表决,如一个资源的访问规则存在多个并行时,便不能以某一个AccessDecisionVoter的表决作为最终的访问授权结果。AccessDecisionManager的职责便是在这种场景下,汇总所有AccessDecisionVoter的表决结果后给出一个最终的决策。从而导致框架中预设了三种不同决策规则的AccessDecisionManager的实现类。

二、一票通过AffirmativeBased

第一个我们来介绍,Spring Security中默认提供的访问决策模型AffirmativeBased。一句话来说AffirmativeBased的逻辑就是一票通过——当前只要存在任何一个投了赞同表的AccessDecisionVoter便会最终给予相关授权。

affirmative adj. 肯定的;积极的 n. 肯定语;赞成的一方

假设存在资源A,在RoleVoter中要求有Admin的角色,而在MinutedOddVoter中缺只要是奇数分钟则可以访问。那么在AffirmativeBased模型下,即时用于没有Admin的角色,只要满足奇数分钟的条件一样可以访问目标资源。

    @Secured({"IS_AUTHENTICATED_FULLY","ROLE_USER","MINUTE_ODD"})@RequestMapping("/")public String root(@Autowired Authentication authentication) {return "index";}
复制代码

当我们奇数分钟数访问对应资源的时候:

Voter: org.springframework.security.access.vote.RoleVoter@508280a4, returned: -1
Voter: org.springframework.security.access.vote.AuthenticatedVoter@2846f995, returned: -1
Voter: com.newnil.demo.security.MinuteBasedVoter@1ec9ec13, returned: 1
Authorization successful
复制代码

即使RoleVoterAuthenticatedVoter存在明确的反对,但是因为MinuteBasedVoter满足了时间的要求,一样会得到一个肯定的结果。 这边有一个经验,在默认的AffirmativeBased的模型下客制化AccessDecisionVoter如果不是很决定性的规则,诸如一些辅助性的访问限制避免投出明确的赞同表,而是换个角度,投出明确的反对票,如不满足反对的情况可以投出弃权票。我们在上一期客制化的MinuteBasedVoter便是一个不好的反面教材^_^。

三、一票否决UnanimousBased

第二个,我们再来介绍一个备选的决策规则,即UnanimousBased所代表的一票否则制,所有人都没有反对意见。

unanimous adj. 全体一致的;意见一致的;无异议的

其规则也十分容易懂,只要任意一个AccessDecisionVoter投出了反对票,则无论有多少个赞同票都无法授权访问权限。UnanimousBased代表了与AffirmativeBased完全对立的规则,有点类似五常表决的一票否则制,比如前几年著名的新闻“土耳其要求取消俄罗斯的一票否决票,这个提案被俄罗斯一票否决了”。 同样回到代码上来,我们通过调整Java Config配置代码将使用的AccessDecisionManager实现变更为UnanimousBased

@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@Configuration
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {@Overrideprotected AccessDecisionManager accessDecisionManager() {List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList();ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();expressionAdvice.setExpressionHandler(this.getExpressionHandler());decisionVoters.add(new RoleVoter());decisionVoters.add(new AuthenticatedVoter());decisionVoters.add(new MinuteBasedVoter());return new UnanimousBased(decisionVoters);}
}
复制代码

对于同样的场景下,如用户已经登录并拥有了对应的权限而因为当前时间不是偶数分钟,那么最终的决策结果因为有一票否决变为了不可访问

 Voter: org.springframework.security.access.vote.RoleVoter@ddc490, returned: 0Voter: org.springframework.security.access.vote.AuthenticatedVoter@27f66035, returned: 1Voter: com.newnil.demo.security.MinuteBasedVoter@4f6b68aa, returned: -1
Access is denied (user is not anonymous);
复制代码

四、少数服从多数ConsensusBased

最后出场的ConsensusBased可能是三个规则里最“民主”,即少数服从多数制。

consensus n. 一致;舆论;合意 ConsensusBased对所有投票的AccessDecisionVoter的意见进行汇总,以数量多那一方的结果为准。 但是存在一种特殊情况——平票:如果产生平票则根据配置allowIfEqualGrantedDeniedDecisions来判断是否通过,在默认情况下allowIfEqualGrantedDeniedDecisions值是true。

同样的我们修改Java Config来测试下ConsensusBased的行为:

@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true)
@Configuration
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {@Overrideprotected AccessDecisionManager accessDecisionManager() {List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList();ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();expressionAdvice.setExpressionHandler(this.getExpressionHandler());decisionVoters.add(new RoleVoter());decisionVoters.add(new AuthenticatedVoter());decisionVoters.add(new MinuteBasedVoter());ConsensusBased consensusBased = new ConsensusBased(decisionVoters);consensusBased.setAllowIfEqualGrantedDeniedDecisions(false);//可以调整平票逻辑return consensusBased;}
}
复制代码

我们同样在偶数分钟访问,在登录后访问受限制的资源:

Voter: org.springframework.security.access.vote.RoleVoter@2c1ae72c, returned: 1
Voter: org.springframework.security.access.vote.AuthenticatedVoter@60d5234, returned: 1
Voter: com.newnil.demo.security.MinuteBasedVoter@6a34393c, returned: -1
Authorization successful
复制代码

与之前UnanimousBased的表现不同,因为赞同票大于否对票所以我们最终还是获取了访问的权限。

结尾

作为访问控制的最后一个组件,由于有了之前的铺垫和了解,三种决策规则相比之下会显得简单很多。并且在通常的情况下,对于AccessDecisionManager我们也不太会存在任何客制化的可能性。我们只需要了解如何选择合适的AccessDecisionManager与如何编写相关的Java配置代码即可。 从下一期开始,我们将进入新的主题开始介绍Spring Security中的config包下关于配置的一些内容。 我们下期再见。

转载于:https://juejin.im/post/5cbe69b06fb9a031fb2cd27a

Spring Security教程 Vol 9. AccessDecisionManager组件介绍相关推荐

  1. Spring Security教程

    Spring Security教程 Web系统中登录认证(Authentication)的核心就是凭证机制,无论是Session还是JWT,都是在用户成功登录时返回给用户一个凭证,后续用户访问接口需携 ...

  2. 史上最简单的Spring Security教程(十九):AccessDecisionVoter简介及自定义访问权限投票器

    为了后续对 AccessDecisionManager 的介绍,我们先来提前对 AccessDecisionVoter 做个简单的了解,然后,在捎带手自定义一个 AccessDecisionVoter ...

  3. Spring Security 教程

    Spring Security 教程 在这篇文章中,我们将讨论Spring框架 "安全性"模块基础知识.我们将在即将发布的帖子中开发一些简单而先进的示例. 现在,开发安全应用程序是 ...

  4. Spring Security小教程 Vol 2. Authentication核心组件介绍

    前言 上一期我们介绍了如何最简单的为一个SpringBoot应用添加Spring Security框架,并使其为应用完成用户鉴权和访问控制的授权服务. 这一期我们将聚焦在用户鉴权部分,用户鉴权又可以从 ...

  5. 史上最简单的Spring Security教程(二十八):CA登录与默认用户名密码登录共存详细实现及配置

    ​在前面的文章中,我们自定义了一些CA登录相关的类,如 CertificateAuthorityAuthenticationToken.CertificateAuthorityAuthenticati ...

  6. Spring Security教程 第一弹 初识spring security

    写在前面的话 更多Spring与微服务相关的教程请戳这里 Spring与微服务教程合集 1.概述 核心概念: 认证 授权:Spring Security不仅支持基于URL对Web的请求授权,还支持方法 ...

  7. Spring Security:身份验证令牌Authentication介绍与Debug分析

    在Spring Security中,通过Authentication来封装用户的验证请求信息,Authentication可以是需要验证和已验证的用户请求信息封装.接下来,博主介绍Authentica ...

  8. Spring Security:身份验证入口AuthenticationEntryPoint介绍与Debug分析

    ExceptionTranslationFilter ExceptionTranslationFilter(Security Filter)允许将AccessDeniedException和Authe ...

  9. microsoftsql新建登录用户登录失败_史上最简单的Spring Security教程(九):自定义用户登录失败页面...

    生活中肯定存在这样的场景,在登录某个网站时,难免会忘记密码,或是验证码输入错误,造成多次尝试.所以,有必要适度的提醒用户,到底是什么原因造成了登录失败,如用户名密码不正确.验证码错误等等.由于 Spr ...

最新文章

  1. SQL查询语句大全集锦(一)
  2. DockingManager的使用入门
  3. poj 3486 A Simple Problem with Integers(树状数组第三种模板改段求段)
  4. npm 更换插件版本_Node CLI 工具的插件方案探索
  5. mongoose使用简记
  6. 算法的时间复杂度[ZT]
  7. linux内存布局和地址空间布局随机化(ASLR)下的可分配地址空间
  8. tensorflow : gfile 函数
  9. 《JavaScript高级程序设计》Chapter 10 DOM
  10. mysql5.7 yum 密码,CentOS 7.7解决yum方式安装的MySQL 5.7 root用户密码丢失问题
  11. 汇编实验一 查看CPU和内存,用机器指令和汇编语言指令编程
  12. python循环结构高一信息技术_高一信息技术For循环语句公开课【2019原创资源大赛】...
  13. ui-grid 使用讲解
  14. python中字典keys、values、items的使用_Python学习笔记字典之keys()、values()和 items()方法...
  15. 【USACO题库】5.2.1 Snail Trails蜗牛的旅行
  16. 数据库三级考试 真题存储过程汇总(含答案)
  17. 指导手册05:MapReduce编程入门.md
  18. BZOJ_4698_Sdoi2008 Sandy的卡片_后缀数组+单调队列+双指针
  19. linux驱动原载-- touch pannel驱动
  20. 二---------

热门文章

  1. 2018年年度总结,以及2019年规划
  2. 读取手机联系人,并用listview显示
  3. 第十、十一周项目一-点-圆-圆柱类族的设计(1)
  4. React创建组件的三种方式及其区别
  5. 互联网思维-产品思维(1)
  6. C语言函数集(十四)
  7. (008) java后台开发之java程序中的控制结构
  8. python能实现excel什么功能_Python pandas对excel的操作实现示例
  9. Flutter中通过循环渲染组件
  10. SpringMVC源码解析