[Spring3.x源码]Ageci(二)授权器

2023-11-01

上一篇中配置的FilterSecurityInterceptor即是授权器

FilterSecurityInterceptor.doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
	FilterInvocation fi = new FilterInvocation(request, response, chain);
	invoke(fi);
}
public void invoke(FilterInvocation fi) throws IOException, ServletException {
        if ((fi.getRequest() != null) && (fi.getRequest().getAttribute(FILTER_APPLIED) != null)
            && observeOncePerRequest) {
            // filter already applied to this request and user wants us to observce
            // once-per-request handling, so don't re-do security checking
            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
        } else {
            // first time this request being called, so perform security checking
            if (fi.getRequest() != null) {
                fi.getRequest().setAttribute(FILTER_APPLIED, Boolean.TRUE);
            }

            InterceptorStatusToken token = super.beforeInvocation(fi);

            try {
                fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
            } finally {
                super.afterInvocation(token, null);
            }
        }
    }
1.InterceptorStatusToken token = super.beforeInvocation(fi);

	protected InterceptorStatusToken beforeInvocation(Object object) {
		Assert.notNull(object, "Object was null");
	
		if (!getSecureObjectClass().isAssignableFrom(object.getClass())) {
			throw new IllegalArgumentException("Security invocation attempted for object "
					+ object.getClass().getName()
					+ " but AbstractSecurityInterceptor only configured to support secure objects of type: "
					+ getSecureObjectClass());
		}
	
		ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource().getAttributes(object);
	
		if (attr == null) {
			if (rejectPublicInvocations) {
				throw new IllegalArgumentException(
						"No public invocations are allowed via this AbstractSecurityInterceptor. "
								+ "This indicates a configuration error because the "
								+ "AbstractSecurityInterceptor.rejectPublicInvocations property is set to 'true'");
			}
	
			if (logger.isDebugEnabled()) {
				logger.debug("Public object - authentication not attempted");
			}
	
			publishEvent(new PublicInvocationEvent(object));
	
			return null; // no further work post-invocation
		}
	
		if (logger.isDebugEnabled()) {
			logger.debug("Secure object: " + object.toString() + "; ConfigAttributes: " + attr.toString());
		}
	
		if (SecurityContextHolder.getContext().getAuthentication() == null) {
			credentialsNotFound(messages.getMessage("AbstractSecurityInterceptor.authenticationNotFound",
					"An Authentication object was not found in the SecurityContext"), object, attr);
		}
	
		// Attempt authentication if not already authenticated, or user always
		// wants reauthentication
		Authentication authenticated;
	
		if (!SecurityContextHolder.getContext().getAuthentication().isAuthenticated() || alwaysReauthenticate) {
			try {
				authenticated = this.authenticationManager.authenticate(SecurityContextHolder.getContext()
						.getAuthentication());
			}
			catch (AuthenticationException authenticationException) {
				throw authenticationException;
			}
	
			// We don't authenticated.setAuthentication(true), because each
			// provider should do that
			if (logger.isDebugEnabled()) {
				logger.debug("Successfully Authenticated: " + authenticated.toString());
			}
	
			SecurityContextHolder.getContext().setAuthentication(authenticated);
		}
		else {
			authenticated = SecurityContextHolder.getContext().getAuthentication();
	
			if (logger.isDebugEnabled()) {
				logger.debug("Previously Authenticated: " + authenticated.toString());
			}
		}
	
		// Attempt authorization
		try {
			this.accessDecisionManager.decide(authenticated, object, attr);
		}
		catch (AccessDeniedException accessDeniedException) {
			AuthorizationFailureEvent event = new AuthorizationFailureEvent(object, attr, authenticated,
					accessDeniedException);
			publishEvent(event);
	
			throw accessDeniedException;
		}
	
		if (logger.isDebugEnabled()) {
			logger.debug("Authorization successful");
		}
	
		AuthorizedEvent event = new AuthorizedEvent(object, attr, authenticated);
		publishEvent(event);
	
		// Attempt to run as a different user
		Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attr);
	
		if (runAs == null) {
			if (logger.isDebugEnabled()) {
				logger.debug("RunAsManager did not change Authentication object");
			}
	
			// no further work post-invocation
			return new InterceptorStatusToken(authenticated, false, attr, object);
		}
		else {
			if (logger.isDebugEnabled()) {
				logger.debug("Switching to RunAs Authentication: " + runAs.toString());
			}
	
			SecurityContextHolder.getContext().setAuthentication(runAs);
	
			// revert to token.Authenticated post-invocation
			return new InterceptorStatusToken(authenticated, true, attr, object);
		}
	}
1.1、ConfigAttributeDefinition attr = this.obtainObjectDefinitionSource().getAttributes(object);
解析配置文件中配置到objectDefinitionSource对象中的值。

之后去SecurityContextHolder中获取Authentication对象。如果没有的话,要解析一次。而SecurityContextHolder中的Authentication对象是在上一篇,验证成功后AbstractProcessingFilter.successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
    Authentication authResult)方法中保存进去的。

1.2、this.accessDecisionManager.decide(authenticated, object, attr);
private AccessDecisionManager accessDecisionManager;来自配置文件accessDecisionManager
以AffirmativeBased为例,一票否决制:

	public void decide(Authentication authentication, Object object, ConfigAttributeDefinition config)
		throws AccessDeniedException {
		Iterator iter = this.getDecisionVoters().iterator();
		int deny = 0;
		
		while (iter.hasNext()) {
		    AccessDecisionVoter voter = (AccessDecisionVoter) iter.next();
		    int result = voter.vote(authentication, object, config);
		
		    switch (result) {
		    case AccessDecisionVoter.ACCESS_GRANTED:
		        return;
		
		    case AccessDecisionVoter.ACCESS_DENIED:
		        deny++;
		
		        break;
		
		    default:
		        break;
		    }
		}
		
		if (deny > 0) {
		    throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
		            "Access is denied"));
		}
		
		// To get this far, every AccessDecisionVoter abstained
		checkAllowIfAllAbstainDecisions();
	}
this.getDecisionVoters().iterator(),遍历投票器
也是在配置文件中配置,以AuthenticatedVoter为例

public int vote(Authentication authentication, Object object, ConfigAttributeDefinition config) {
    int result = ACCESS_ABSTAIN;
    Iterator iter = config.getConfigAttributes();

    while (iter.hasNext()) {
        ConfigAttribute attribute = (ConfigAttribute) iter.next();

        if (this.supports(attribute)) {
            result = ACCESS_DENIED;

            if (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())) {
                if (isFullyAuthenticated(authentication)) {
                    return ACCESS_GRANTED;
                }
            }

            if (IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())) {
                if (authenticationTrustResolver.isRememberMe(authentication)
                    || isFullyAuthenticated(authentication)) {
                    return ACCESS_GRANTED;
                }
            }

            if (IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute())) {
                if (authenticationTrustResolver.isAnonymous(authentication) || isFullyAuthenticated(authentication)
                    || authenticationTrustResolver.isRememberMe(authentication)) {
                    return ACCESS_GRANTED;
                }
            }
        }
    }

    return result;
}

public boolean supports(ConfigAttribute attribute) {
    if ((attribute.getAttribute() != null)
        && (IS_AUTHENTICATED_FULLY.equals(attribute.getAttribute())
        || IS_AUTHENTICATED_REMEMBERED.equals(attribute.getAttribute())
        || IS_AUTHENTICATED_ANONYMOUSLY.equals(attribute.getAttribute()))) {
        return true;
    } else {
        return false;
    }
}

public static final String IS_AUTHENTICATED_FULLY = "IS_AUTHENTICATED_FULLY";
public static final String IS_AUTHENTICATED_REMEMBERED = "IS_AUTHENTICATED_REMEMBERED";
public static final String IS_AUTHENTICATED_ANONYMOUSLY = "IS_AUTHENTICATED_ANONYMOUSLY";
当然,我们也可以写自己的Voter,加到配置中,完成相关业务操作。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[Spring3.x源码]Ageci(二)授权器 的相关文章

  • Android平台 Target API level 升级到 31,在Android 12上启动黑屏卡死

    项目场景 项目上架平台要求android API需要升级到31及以上才行 API升级到33版本后经测试在android12 13机型上会卡在启动页面 打开调试日志也没报错 问题描述 Android平台 Target API level 升级
  • 阿里云服务器Windows Server 2008 架设 Web 服务器教程(图文详解)

    最近刚忙完嵌入式下位机LWIP的网络通讯 希望将嵌入式设备接入云端来进行控制 买了一个阿里云Windows server 2008服务器 来搭建云服务器 过程给大家分享一下互相学习 让小白快速上手 通过win R打开命令终端 输入mstsc
  • HectorSLAMGmappingKartoSLAMCoreSLAMLagoSLAM

    1 算法介绍 A HectorSLAM scan matching Gaussian Newton equation 传感器的要求高 要求 高更新频率小测量噪声的激光扫描仪 不需要里程计 使空中无人机与地面小车在不平坦区域运行存在运用的可能
  • umi,从url中获得search参数方法

    1 路由传参 新增时不带ID search或者 query history push pathname addSelf query self yes 2 从url中取参数 import history useLocation from um
  • 最小熵原理系列:词向量的维度应该怎么选择?

    PaperWeekly 原创 作者 苏剑林 单位 追一科技 研究方向 NLP 神经网络 随着 NLP 的发展 像 Word2Vec Glove 这样的词向量模型 正逐渐地被基于 Transformer 的 BERT 等模型代替 不过经典始终
  • Linux系统下word转pdf,xls转pdf,ppt转pdf

    word转换pdf的技术方案 供参考 doc docx ppt pptx xls xlsx均支持转换 本方案是Java结合shell命令完成 不同于以往的仅依赖java组件转换或打印pdf的方案 需要目标服务器安装office套件 可选方案
  • LayUI登录页面

    使用LayUI对你所做系统进行前端的美化和交互完善设计 使得系统的操作和交互更加符合人机交互理念 下面文章仅是登录页面的美化
  • 国际期货是什么?正大期货的定义怎么来的?

    国际期货市场是国际上进行期货交易的市场 期货交易是预先签订商品买卖合同 而贷款的支付和货物的交割要在约定的时间内进行的一种交易 但一般不需要真正交割 绝大多数合约在到期前对冲 期货交易只需支付少量保证金 通过期货交易所买进卖出期货合约 即一
  • Anaconda配置OpenCV环境

    1 移除旧的环境 如果原来有一个opencv的环境 那么要先进行这个环境的删除 conda env remove opencv 2 虚拟环境创建 首先进行虚拟环境的创建 使用Anaconda进行虚拟环境的创建 我这里的虚拟环境的名称是 op
  • Java如何让自定义类型具有可比较大小的能力

    自定义类型大小比较 一 背景 二 两种方法 方式一 自然排序 方式二 定制排序 一 背景 Java中基本数据类型之间可以使用比较运算符 gt lt gt lt 等进行比较 引用数据类型之间进行比较时 使用继承于Object类的equals方
  • atheros面试

    6道题目 1 是swap的宏的定义 2 用一个语句判断一个数是不是2的n次幂 3 判断sizeof作为参数传入的 char 的长度 4 用两个栈实现一个队列 5 将字符串bcde转换为edcb 6 循环计数1 n 如果计到m 则打印出来 第
  • Impala 三大组件:Impala Daemon, Impala Statestore, Impala Catelog

    Impala 三大组件 Impala Daemon 功能 负责读写数据文件 接受来自 Impala shell ODBC Hue 和 JDBC 的查询请求 然后与集群中的其他节点分布式并行工作 将本节点的查询结果返回给中心协调者节点 查询流
  • 创建项目Vue 3 + Vite,引入 Element Plus UI 组件库。

    首先要下载vite 在终端输入npm init vitejs app my vue app template vue 快速生成一个使用 Vite 构建的 Vue 3 项目模版 这时候如果是第一次创建 电脑就会提示 只用输入y 电脑即可自动下
  • 高通9008刷机

    1 进入9008模式 第一种方法 adb reboot edl 第二种方法 手机按钮进入 第三种方法 小米安全通线 第四种方法 短路接点 2 需要安装安卓驱动 高通驱动 QFIL软件 3 需要下载ROM包 4 解压ROM包 5 打开QFIL
  • 毕业季

    进入六月 毕业的氛围越来越浓 虽然忙 但更多的是不舍 四年 转眼之间 大一在高密校区的岁月仍历历在目 6 10 从公司请假 早上八点半去图书馆布置创新比赛的展板 6 11 休整一天 PPT准备6 12号早上的答辩 6 12 早八点半 在中德
  • 欧科云链让科技赋能乡村教育,获公益时报等主流媒体报道...

    中国经济网 公益时报前线报道 近日 欧科云链CSR团队到访饶河县饶河农场中心小学 为该校的人工智能创客实验室注入了新的活力 这一举措旨在助力学校推进人工智能教育 为农村学生提供更广阔的发展机会 饶河农场中心小学一直以来致力于创新教育 自20
  • nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 的解决办法

    问题概述 在基于微服务架构风格的项目开发过程中 为了提高快速开发的目的 提高开发效率 集成了 MyBatisPlus 对于 MyBatisPlus 封装的 CRUD API 接口已经非常强大了 但是有时还是需要使用其动态 SQL 的拼接 在
  • 性能测试之性能优化篇

    目录 为什么进行性能测试 性能测试的目的 服务性能优化的思考 衡量系统性能常用的指标 系统性能计数器 性能测试分类 如何合理的规划我们的架构性能 最后拿数据说话 性能优化原则 性能优化的方法 性能优化的分层思想 所有的优化都会对系统性能产生
  • flask 文件 服务器,flask服务器文件上传云

    flask服务器文件上传云 内容精选 换一换 弹性云服务器支持通过内网访问OBS OBS可供用户存储任意类型的数据 将图片 视频等数据存储至OBS后 在ECS上可以访问OBS 下载桶中的图片或视频等数据 通过内网访问OBS 可以避免因网络不
  • ASP.NET中JSON的序列化和反序列化

    在项目开发过程中 发现需要用到JSON序列化 反序列化的问题 所有 在网上找到了一下这篇文章 摘录了下来 摘自 http www cnblogs com zhaozhan archive 2011 01 09 1931340 html JS

随机推荐

  • 使用ijkplayer播放4k视频卡顿的解决方法

    使用ijkplayer播放4k视频卡顿的解决方法 使用硬解码 ijkMediaPlayer setOption IjkMediaPlayer OPT CATEGORY PLAYER mediacodec 1
  • PAT甲级1135

    红黑树的特点 1 根节点是黑色 2 如果一个节点是红色那么他的两个子节点都是红色 3 任意从根节点到叶子结点的路径上 所有的路径经过的黑色节点数相同 4 红黑树是二叉搜索树 算法 1 根节点是否为黑色 2 红色节点的两个子节点是不是都是黑色
  • JS 数组或对象的遍历(for、for...in、for...of、foreach)

    转载自 JavaScript 比较for for in for of forEach的区别 非早起选手的博客 CSDN博客 目录 一 for 二 for in 三 for of 四 forEach 五 小结 一 for 最原始的方法 用来遍
  • 【在线教育】- 前端环境搭建&讲师CURD前端实现

    在线教育 一 在线教育前端环境搭建 1 1 vue element admin 概述 1 2 vue element admin master安装 1 3 vue element template介绍 了解 1 4 vue element
  • 牛客面试高频算法题js(输出二叉树的右视图、岛屿数量、矩阵的最小路径和、字符串出现次数的TopK问题、二叉树根节点到叶子节点的所有路径和)

    NC136 输出二叉树的右视图 描述 请根据二叉树的前序遍历 中序遍历恢复二叉树 并打印出二叉树的右视图 数据范围 0 le n le 100000 n 10000 要求 空间复杂度 O n O n 时间复杂度 O n O n 如输入 1
  • html跳转页面到自己写的另一个页面,非js

    最简单的跳转页面 记录给渣渣的自己 很low的两个html界面1和2 在1页面上设置一个button 按下按钮 跳转至自己写的2界面 代码如下 div class wrapper div class container h1 Welcome
  • Sqli-labs 15-19

    15关 在输入框内测试Username asd Password 123并点击提交后发现并没有什么卵用 在Username处尝试万能钥匙1 or 1 1 发现成功登录了 接下来看源码分析问题 由于红下划线处的username uname 所
  • 移动app开发如何做接口的版本控制

    移动app为什么要做版本控制 应用升级无法做到全部升级 比如某应用现行1 1版本 某次开发升级后 版本变为1 2 除app界面变化外 后台接口也发生了变化 然而不是所有的用户都在第一时间升级了app 或者由于版本推送不及时 用户忽略更新等原
  • 2020浙江大学软件学院预推免经验

    个人背景 本人为末流211计算机科学与技术专业 且专业排名于保研名额末尾 但是综合排名在中上肯定有保研资格 本科学校最后是以综合排名上报学信网的 而预推免和夏令营对方学校对看的一般是专业排名 预推免报名时本科学校已经出了推免名单了 所以预推
  • Datadog 能成为最大的云监控厂商吗

    Datadog 原本是一家名不见经传的云监控公司 于 2019年9月19日 登陆纳斯达克 上市首日即突破 80亿 美金 上市前还搞了个小插曲 思科在 IPO 前夕提出 70亿美元 全面收购要约 被 Datadog 董事会断然拒绝 时至今日
  • leetcode 55. 跳跃游戏

    一 题意 给定一个非负整数数组 nums 你最初位于数组的第一个下标 数组中的每个元素代表你在该位置可以跳跃的最大长度 判断你是否能够到达最后一个下标 二 解法 贪心算法 解法1 计算出 i n u m s
  • Qt程序启动画面播放(gif与swf两种动画格式) - 路上的脚印

    学习Qt有一段时间了 发现一个小问题 网上关于Qt的资料或者总结性的学习及应用文章有点少 比如 Qt完整的API 程序运行之前的启动画面如何按理想效果播放等 每次想在项目中添加一些应用的时候 总是找不到好的书籍或文章可以马上学习 上手 今天
  • 淘宝、1688、京东、拼多多,抖音五个平台的区别分析

    淘宝 淘宝是中国最大的C2C电子商务平台 也是消费者购物的首选平台 淘宝上的商品种类繁多 价格实惠 同时还有很多优惠活动和促销活动 让消费者可以以较低的价格购买到高质量的商品 1688 1688是中国最大的批发市场之一 有数百万的商家在上面
  • Qt为release中可执行程序添加库进行打包并结合inno setup打包生成exe安装文件

    Qt为release中可执行程序添加库进行打包并结合inno setup打包生成exe安装文件 文章目录 Qt为release中可执行程序添加库进行打包并结合inno setup打包生成exe安装文件 一 Qt为release中可执行程序添
  • fedora11下gmlive0.22beta源代码安装

    1 解决依赖问题 否则会出现问题 No package gtkmm 2 4 found No package libglademm 2 4 found 安装依赖包 yum install gtkmm24 dev yum insttall l
  • C# 海康人脸识别设备初开发(二)话不多说以下完整例子

    demo截图 demo下载地址 https download csdn net download qq 16632449 11002228 以下完善了计划权限 可以参考下 其他的没了 如果提示错误23 基本是设备不支持 那你就要去问下海康的
  • Spring boot定时任务@Scheduled

    文章目录 1 前言 2 pom包配置 3 启动类启用定时 4 创建定时任务实现类 5 补充 cron表达式 6 遇到的坑 1 前言 Scheduled 参数可以接受两种定时的设置 一种是我们常用的cron 6 一种是 fixedRate 6
  • C++11:委派构造函数

    委派构造函数
  • TM1650数码管(类IIC驱动)

    目录 一 TM1650简介 1 特性描述 2 功能特点 二 IIC Inter Integrated Circuit BUS 结构解析 1 IIC协议介绍 2 多主机IIC总线结构 3 信号概念 三 TM1650数码管的工作 四 编写代码
  • [Spring3.x源码]Ageci(二)授权器

    上一篇中配置的FilterSecurityInterceptor即是授权器 FilterSecurityInterceptor doFilter ServletRequest request ServletResponse response