1、三种表决方式,默认是 一票制AffirmativeBased

public interface AccessDecisionManager {
/**
* 通过传递的参数来决定用户是否有访问对应受保护对象的权限
* @param authentication 当前正在请求受包含对象的Authentication
* @param object 受保护对象,其可以是一个MethodInvocation、JoinPoint或FilterInvocation。
* @param configAttributes 与正在请求的受保护对象相关联的配置属性
*/
void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException;

/*表示当前AccessDecisionManager是否支持对应的ConfigAttribute*/
boolean supports(ConfigAttribute attribute);

/*表示当前AccessDecisionManager是否支持对应的受保护对象类型*/
boolean supports(Class<?> clazz);
}

decide()方法用于决定authentication是否符合受保护对象要求的configAttributes。
supports(ConfigAttribute attribute)方法是用来判断AccessDecisionManager是否能够处理对应的ConfigAttribute的。
supports(Class<?> clazz)方法用于判断配置的AccessDecisionManager是否支持对应的受保护对象类型。

Spring Security内置了三个基于投票的AccessDecisionManager实现类,它们分别是AffirmativeBased、ConsensusBased和UnanimousBased。

AffirmativeBased的逻辑是这样的:

(1)只要有AccessDecisionVoter的投票为ACCESS_GRANTED则同意用户进行访问;

(2)如果全部弃权也表示通过;

(3)如果没有一个人投赞成票,但是有人投反对票,则将抛出AccessDeniedException。

ConsensusBased的逻辑是这样的:

(1)如果赞成票多于反对票则表示通过。

(2)反过来,如果反对票多于赞成票则将抛出AccessDeniedException。

(3)如果赞成票与反对票相同且不等于0,并且属性allowIfEqualGrantedDeniedDecisions的值为true,则表示通过,否则将抛出异常AccessDeniedException。参数allowIfEqualGrantedDeniedDecisions的值默认为true。

(4)如果所有的AccessDecisionVoter都弃权了,则将视参数allowIfAllAbstainDecisions的值而定,如果该值为true则表示通过,否则将抛出异常AccessDeniedException。参数allowIfAllAbstainDecisions的值默认为false。

UnanimousBased的逻辑与另外两种实现有点不一样,另外两种会一次性把受保护对象的配置属性全部传递给AccessDecisionVoter进行投票,而UnanimousBased会一次只传递一个ConfigAttribute给AccessDecisionVoter进行投票。这也就意味着如果我们的AccessDecisionVoter的逻辑是只要传递进来的ConfigAttribute中有一个能够匹配则投赞成票,但是放到UnanimousBased中其投票结果就不一定是赞成了。UnanimousBased的逻辑具体来说是这样的:

(1)如果受保护对象配置的某一个ConfigAttribute被任意的AccessDecisionVoter反对了,则将抛出AccessDeniedException。

(2)如果没有反对票,但是有赞成票,则表示通过。

(3)如果全部弃权了,则将视参数allowIfAllAbstainDecisions的值而定,true则通过,false则抛出AccessDeniedException。

配置方式

投票器列表 - decisionVoters属性

默认的AccessDecisionManager要求我们配置投票器的一个属性,decisionVoters属性,它们将会在认证决策时用到。

在我们不声明AccessDecisionManager时,decisionVoters属性是自动配置的,配置的是1-多个投票器。

2、两种默认投票器:RoleVoter和AuthenticatedVoter

2.1、RoleVoter

RoleVoter是Spring Security内置的一个AccessDecisionVoter,其会将ConfigAttribute简单的看作是一个角色名称,在投票的时如果拥有该角色即投赞成票。

如果ConfigAttribute是以“ROLE_”开头的,则将使用RoleVoter进行投票。

当用户拥有的权限中有一个或多个能匹配受保护对象配置的以“ROLE_”开头的ConfigAttribute时其将投赞成票;

如果用户拥有的权限中没有一个能匹配受保护对象配置的以“ROLE_”开头的ConfigAttribute,则RoleVoter将投反对票;

如果受保护对象配置的ConfigAttribute中没有以“ROLE_”开头的,则RoleVoter将弃权。

2.2、AuthenticatedVoter

AuthenticatedVoter也是Spring Security内置的一个AccessDecisionVoter实现。其主要用来区分匿名用户、通过Remember-Me认证的用户和完全认证的用户。

完全认证的用户是指由系统提供的登录入口进行成功登录认证的用户。

AuthenticatedVoter可以处理的ConfigAttribute有IS_AUTHENTICATED_FULLY、IS_AUTHENTICATED_REMEMBERED和IS_AUTHENTICATED_ANONYMOUSLY。

如果ConfigAttribute不在这三者范围之内,则AuthenticatedVoter将弃权。

否则将视ConfigAttribute而定,

如果ConfigAttribute为 IS_AUTHENTICATED_ANONYMOUSLY,则不管用户是匿名的还是已经认证的都将投赞成票;

如果ConfigAttribute为 IS_AUTHENTICATED_REMEMBERED,则仅当用户是由Remember-Me自动登录,或者是通过登录入口进行登录认证时才会投赞成票,否则将投反对票;

如果ConfigAttribute为 IS_AUTHENTICATED_FULLY时, 则仅当用户是通过登录入口进行登录的才会投赞成票,否则将投反对票。

AuthenticatedVoter是通过AuthenticationTrustResolver的isAnonymous()方法和isRememberMe()方法来判断SecurityContextHolder持有的Authentication是否为AnonymousAuthenticationToken或RememberMeAuthenticationToken的,

即是否为IS_AUTHENTICATED_ANONYMOUSLY和IS_AUTHENTICATED_REMEMBERED。

2.3、支持自定义投票器:实现AccessDecisionVoter接口并在配置中添加我们的实现

3、使用 Spring 表达式语言配置访问控制

3.1、配置 use-expressions="true"

添加后将要修改用来进行拦截器规则声明的 access 属性,改为 SpEL 表达式。 SpEL 允许使用特定的访问控制规则表达式语言。

与简单的字符串如 ROLE_USER 不同,配置文件可以指明表达式语言触发方法调用、引用系统属性、计算机值等等。

SpEL 的语法与其他的表达式语言很类似,如在 Tapestry 等框架中用到的 Object Graph Notation Language (OGNL) ,以及用于 JSP 和 JSF 的 Unified Expression Language 。

3.2、使用表达式后的role处理

如果你通过使用 use-expressions 属性启用了 SpEL 表达式访问控制,将会使得自动配置的 RoleVoter 实效,后者能够使用角色的声明,正如在前面的例子所见到的那样:

<intercept-url pattern="/*" access="ROLE_USER"/>

这意味着如果你仅仅想通过角色来过滤请求的话,访问控制声明必要要进行修改。幸运的的是,这已经被充分考虑过了,一个 SpEL 绑定的方法 hasRole 能够检查角色。

3.3、使用表达式的一些例子

Spring Security入门(1-13)Spring Security的投票机制和投票器的更多相关文章

  1. spring boot 入门一 构建spring boot 工程

    最近在学习Spring boot,所以想通过博客的形式和大家分享学习的过程,同时也为了更好的学习技术,下面直接进入Spring boot的世界. 简介 spring boot 它的设计目的就是为例简化 ...

  2. spring Boot 入门--为什么用spring boot

    为什么用spring boot 回答这个问题不得不说下spring 假设你受命用Spring开发一个简单的Hello World Web应用程序.你该做什么? 我能想到一些 基本的需要.  一个项目 ...

  3. Spring Boot入门(13)自制音乐平台

      经过笔者这几天的辛勤劳作(其实就是苦逼地码代码),一个新的网站已经上线啦!该网站是用Spring Boot工具写的,主要实现的功能如下: 根据歌曲名称和音乐平台搜索歌曲,并实现歌曲的在线播放: 歌 ...

  4. Spring Boot入门篇(基于Spring Boot 2.0系列)

    1:概述: Spring Boot是用来简化Spring应用的初始化开发过程. 2:特性: 创建独立的应用(jar|war形式); 需要用到spring-boot-maven-plugin插件 直接嵌 ...

  5. Spring框架学习(7)spring mvc入门

    内容源自:spring mvc入门 一.spring mvc和spring的关系 spring mvc是spring框架提供的七层体系架构中的一个层,是spring框架的一部分,是spring用于处理 ...

  6. Spring Security 入门(一)

    当你看到这篇文章时,我猜你肯定是碰到令人苦恼的问题了,我希望本文能让你有所收获. 本人几个月前还是 Spring 小白,几个月走来,看了 Spring,Spring boot,到这次的 Spring ...

  7. Spring Security 入门(1-1)Spring Security是什么?

    1.Spring Security是什么? Spring Security 是一个安全框架,前身是 Acegi Security , 能够为 Spring企业应用系统提供声明式的安全访问控制. Spr ...

  8. Spring Security 入门

    一.Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配 ...

  9. SpringBoot集成Spring Security入门体验

    一.前言 Spring Security 和 Apache Shiro 都是安全框架,为Java应用程序提供身份认证和授权. 二者区别 Spring Security:重量级安全框架 Apache S ...

随机推荐

  1. TrueCrypt

    其实很早之前就知道这个软件,不过之前没有使用,今天折腾了一把,记录下使用过程中遇见的一些问题. 百度百科: TrueCrypt,是一款免费开源的加密软件,同时支持Windows Vista,7/XP, ...

  2. SignalR Self Host+MVC等多端消息推送服务(2)

    一.概述 上次的文章中我们简单的实现了SignalR自托管的服务端,今天我们来实现控制台程序调用SignalR服务端来实现推送信息,由于之前我们是打算做审批消息推送,所以我们的demo方向是做指定人发 ...

  3. python爬微信公众号前10篇历史文章(3)-lxml&xpath初探

    理解lxml以及xpath 什么是lxml? python中用来处理XML和HTML的library.与其他相比,它能提供很好的性能, 并且它支持XPath. 具体可以查看官方文档->http: ...

  4. 为什么会有可恶的腾讯电脑管家&怎么干掉它-电脑开机出现腾讯电脑管家-无法卸载腾讯电脑管家

    为什么会有可恶的腾讯电脑管家 怎么干掉它 电脑开机出现腾讯电脑管家 无法卸载腾讯电脑管家 某天,趁空闲,升级了一些常用软件,其中就升了新版电脑qq,晚上玩完电脑后关机睡觉,第二天早上开机.出现了图一: ...

  5. 笔记:XML-解析文档-DOM

    要处理XML文档,就要先解析(parse)他,解析器时这样一个程序,读入一个文件,确认整个文件具有正确的格式,然后将其分解成各种元素,使得程序员能够访问这些元素,Java库提供了两种XML解析器: 像 ...

  6. 记录一则ASM实例阻塞,rbal进程异常的案例

    1.故障现象描述 2.确认故障现象 3.排查ASM层面 4.解决问题 1.故障现象描述 环境:AIX 7.1 + Standalone Oracle 11.2.0.4 现象:客户反映某11g版本的AD ...

  7. 【jQuery】 jQuery基础

    jQuery 之前在JS的文章中提到过,JS虽然功能全面但是仍然比较接近底层,代码写起来很麻烦,而以jQuery为代表的JS库包装了很多功能,可以让代码更加简单.接下来就来简单地记录一下我学习和所知道 ...

  8. 【HTML】 HTML基础知识 一些标签

    额..是这样的,去年为了学习web框架,自己开发了一个zbx配置管理的二次开发系统,当时从零开始接触web开发,也第一次接触到了前端的一些知识.其中最基础的就是html/css了.我把那部分笔记整理上 ...

  9. Algorithm --> 判读是否是子树

    问题 判断一棵树是否是另一棵树的子树,如图 思路 问题分两步: 找值相同的根结点(遍历解决) 判断两结点是否包含(递归:值.左孩子.右孩子分别相同) 树节点定义 struct TreeNode { i ...

  10. (转)[置顶] Android APK反编译就这么简单 详解(附图) .

    在学习Android开发的过程你,你往往会去借鉴别人的应用是怎么开发的,那些漂亮的动画和精致的布局可能会让你爱不释手,作为一个开发者,你可能会很想知道这些效果界面是怎么去实现的,这时,你便可以对改应用 ...