spring security配置构建分析

Spring Security安全框架 创建配置类:webSecurityConfigureAdapter(去继承它)(1)查询username、password、validate(用户是否有效)config(HttpSecuritr http):设置访问控制。(2)查询username、authority(权限)布尔类型的字段:用户是否有效。启动项目,自定义进行安全管理(默认的安全管理模式)密码:必须进行加密操作。授权:确定用户的权限,对用户权限进行管理。认证:确认用户是否登录,对登录进行管控。创建工具类(config层)...... 阅读详情

先看一张大图
在这里插入图片描述
从官网给的图中我们可以知道启动是通过封装一个FilterChainProxy 到servlet的filter体系中,来完成安全配置的全套操作。记住这个点,先放着,接着我们来了解spring security 配置模块中几个顶层接口

  • org.springframework.security.config.annotation.SecurityBuilder
  • org.springframework.security.config.annotation.SecurityConfigurer
  • org.springframework.security.config.annotation.ObjectPostProcessor
    首先我们先看SecurityBuilder这个接口,他有一个抽象实现AbstractSecurityBuilder 再来一个扩展抽象实现类AbstractConfiguredSecurityBuilder;类图如下
    在这里插入图片描述
    在顶层接口中只有一个方法
O build() throws Exception;
  • 1

AbstractSecurityBuilder中新增了两个方法并抽象了上层接口的方法

//安全构造对象
public final O build() throws Exception {
		if (this.building.compareAndSet(false, true)) {
			this.object = doBuild();
			return this.object;
		}
		throw new AlreadyBuiltException("This object has already been built");
	}

	//获取被建造的 对象如果不存在则抛出异常
	public final O getObject() {
		if (!this.building.get()) {
			throw new IllegalStateException("This object has not been built");
		}
		return this.object;
	}

	//模板方法留给子类实现
	protected abstract O doBuild() throws Exception;

在来看第二个抽象类AbstractConfiguredSecurityBuilder

public abstract class AbstractConfiguredSecurityBuilder<O, B extends SecurityBuilder<O>>
		extends AbstractSecurityBuilder<O> {
	private final Log logger = LogFactory.getLog(getClass());
	//	初始化需要构造的配置类容器配置类都是SecurityConfigurer的子类
	private final LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>> configurers = new LinkedHashMap<Class<? extends SecurityConfigurer<O, B>>, List<SecurityConfigurer<O, B>>>();
	private final List<SecurityConfigurer<O, B>> configurersAddedInInitializing = new ArrayList<SecurityConfigurer<O, B>>();

	private final Map<Class<? extends Object>, Object> sharedObjects = new HashMap<Class<? extends Object>, Object>();

	private final boolean allowConfigurersOfSameType;

	private BuildState buildState = BuildState.UNBUILT;
	
	private ObjectPostProcessor<Object> objectPostProcessor;

	//构造函数传入需要被spring容器后置处理器处理的对象
	protected AbstractConfiguredSecurityBuilder(
			ObjectPostProcessor<Object> objectPostProcessor) {
		this(objectPostProcessor, false);
	}

	//构造函数,判断在postProcess阶段是被被允许操作的一些行为,例如是否覆盖还是多个配置。
	protected AbstractConfiguredSecurityBuilder(
			ObjectPostProcessor<Object> objectPostProcessor,
			boolean allowConfigurersOfSameType) {
		Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null");
		this.objectPostProcessor = objectPostProcessor;
		this.allowConfigurersOfSameType = allowConfigurersOfSameType;
	}

	//通过推断获取还是构建对象。
	public O getOrBuild() {
		if (isUnbuilt()) {
			try {
				return build();
			}
			catch (Exception e) {
				logger.debug("Failed to perform build. Returning null", e);
				return null;
			}
		}
		else {
			return getObject();
		}
	}

	//传入需要被构建的 配置类,即上面描述的 SecurityConfigurer的所有子类
	//在构建前先到spring ioc容器中过一轮postProcessor的操作,
	//configurer.addObjectPostProcessor这里也就意味着我们可以任意变更
	//已经配置好的所有filter环节。
	@SuppressWarnings("unchecked")
	public <C extends SecurityConfigurerAdapter<O, B>> C apply(C configurer)
			throws Exception {
		configurer.addObjectPostProcessor(objectPostProcessor);
		configurer.setBuilder((B) this);
		add(configurer);
		return configurer;
	}

	//此处直接覆盖现有的任意配置。上面是变更,这里是直接覆盖
	public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
		add(configurer);
		return configurer;
	}

	//保存配置对象用于共享
	@SuppressWarnings("unchecked")
	public <C> void setSharedObject(Class<C> sharedType, C object) {
		this.sharedObjects.put(sharedType, object);
	}

	//获取共享对像
	@SuppressWarnings("unchecked")
	public <C> C getSharedObject(Class<C> sharedType) {
		return (C) this.sharedObjects.get(sharedType);
	}

	//获取所有共享对象
	public Map<Class<? extends Object>, Object> getSharedObjects() {
		return Collections.unmodifiableMap(this.sharedObjects);
	}

	//将配置类对象缓存,确保需要时可以随时取到,开头的配置池
	@SuppressWarnings("unchecked")
	private <C extends SecurityConfigurer<O, B>> void add(C configurer) throws Exception {
		Assert.notNull(configurer, "configurer cannot be null");

		Class<? extends SecurityConfigurer<O, B>> clazz = (Class<? extends SecurityConfigurer<O, B>>) configurer
				.getClass();
		synchronized (configurers) {
			if (buildState.isConfigured()) {
				throw new IllegalStateException("Cannot apply " + configurer
						+ " to already built object");
			}
			List<SecurityConfigurer<O, B>> configs = allowConfigurersOfSameType ? this.configurers
					.get(clazz) : null;
			if (configs == null) {
				configs = new ArrayList<SecurityConfigurer<O, B>>(1);
			}
			configs.add(configurer);
			this.configurers.put(clazz, configs);
			if (buildState.isInitializing()) {
				this.configurersAddedInInitializing.add(configurer);
			}
		}
	}

	//获取缓存的所有配置对象
	@SuppressWarnings("unchecked")
	public <C extends SecurityConfigurer<O, B>> List<C> getConfigurers(Class<C> clazz) {
		List<C> configs = (List<C>) this.configurers.get(clazz);
		if (configs == null) {
			return new ArrayList<>();
		}
		return new ArrayList<>(configs);
	}

	//移除所有配置对象
	@SuppressWarnings("unchecked")
	public <C extends SecurityConfigurer<O, B>> List<C> removeConfigurers(Class<C> clazz) {
		List<C> configs = (List<C>) this.configurers.remove(clazz);
		if (configs == null) {
			return new ArrayList<>();
		}
		return new ArrayList<>(configs);
	}

	//根据类名获取配置对象
	@SuppressWarnings("unchecked")
	public <C extends SecurityConfigurer<O, B>> C getConfigurer(Class<C> clazz) {
		List<SecurityConfigurer<O, B>> configs = this.configurers.get(clazz);
		if (configs == null) {
			return null;
		}
		if (configs.size() != 1) {
			throw new IllegalStateException("Only one configurer expected for type "
					+ clazz + ", but got " + configs);
		}
		return (C) configs.get(0);
	}

	//根据类目移除配置对象
	@SuppressWarnings("unchecked")
	public <C extends SecurityConfigurer<O, B>> C removeConfigurer(Class<C> clazz) {
		List<SecurityConfigurer<O, B>> configs = this.configurers.remove(clazz);
		if (configs == null) {
			return null;
		}
		if (configs.size() != 1) {
			throw new IllegalStateException("Only one configurer expected for type "
					+ clazz + ", but got " + configs);
		}
		return (C) configs.get(0);
	}

	//指定使用的 ObjectPostProcessor
	@SuppressWarnings("unchecked")
	public O objectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor) {
		Assert.notNull(objectPostProcessor, "objectPostProcessor cannot be null");
		this.objectPostProcessor = objectPostProcessor;
		return (O) this;
	}

	//执行postprocess操作,这里即调用了spring ioc容器的postprocess过程
	protected <P> P postProcess(P object) {
		return this.objectPostProcessor.postProcess(object);
	}

	//build 流程
	@Override
	protected final O doBuild() throws Exception {
		synchronized (configurers) {
			buildState = BuildState.INITIALIZING;
			//初始化前
			beforeInit();
			//初始化中
			init();

			buildState = BuildState.CONFIGURING;
			//配置前
			beforeConfigure();
			//配置中
			configure();

			buildState = BuildState.BUILDING;
			//执行build
			O result = performBuild();

			buildState = BuildState.BUILT;
			//返回被build的对象
			return result;
		}
	}

	//可扩展的调用周期
	protected void beforeInit() throws Exception {
	}

	//可扩展
	protected void beforeConfigure() throws Exception {
	}

	//留给子类扩展具体的build过程
	protected abstract O performBuild() throws Exception;
	//初始化过程,即执行所有SecurityConfigurer.init方法
	@SuppressWarnings("unchecked")
	private void init() throws Exception {
		Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
		
		for (SecurityConfigurer<O, B> configurer : configurers) {
			configurer.init((B) this);
		}

		for (SecurityConfigurer<O, B> configurer : configurersAddedInInitializing) {
			configurer.init((B) this);
		}
	}
	//配置过程
	@SuppressWarnings("unchecked")
	private void configure() throws Exception {
		Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();

		for (SecurityConfigurer<O, B> configurer : configurers) {
			configurer.configure((B) this);
		}
	}

	private Collection<SecurityConfigurer<O, B>> getConfigurers() {
		List<SecurityConfigurer<O, B>> result = new ArrayList<SecurityConfigurer<O, B>>();
		for (List<SecurityConfigurer<O, B>> configs : this.configurers.values()) {
			result.addAll(configs);
		}
		return result;
	}

	//推断是否已经build
	private boolean isUnbuilt() {
		synchronized (configurers) {
			return buildState == BuildState.UNBUILT;
		}
	}

	//build 状态
	private static enum BuildState {
		//未执行调用
		UNBUILT(0),
		//初始化方法被执行
		INITIALIZING(1),
		//配置方法被执行
		CONFIGURING(2),
		//构造中
		BUILDING(3),
		//完成构造
		BUILT(4);

		private final int order;

		BuildState(int order) {
			this.order = order;
		}

		public boolean isInitializing() {
			return INITIALIZING.order == order;
		}

		//根据order判断配置顺序
		public boolean isConfigured() {
			return order >= CONFIGURING.order;
		}
	}
}

继承至AbstractConfiguredSecurityBuilder三个类如下

  • org.springframework.security.config.annotation.web.builders.HttpSecurity
  • org.springframework.security.config.annotation.web.builders.WebSecurity
  • org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
    这三个类即为spring构建全部配置的主类
    最开始的三个顶层接口,派生出两个子类即
  • org.springframework.security.config.annotation.web.HttpSecurityBuilder
  • org.springframework.security.config.annotation.web.WebSecurityConfigurer
    这两个类则为spring配置上面三个类的顶层入口。以上三个类同样组装实现了这个接口HttpSecurityBuilder。而WebSecurity 极其子类则将被组装进该builder进行构建。
Spring Security OAuth Client配置加载源码分析 这一节我们以前面默认的OAuth2 客户端集成为例,来了解下配置文件的加载,示例见第二、第三节。 阅读详情

相关推荐

springboot整合SpringSecurity

终极配置:绑定自己的登录页面。他其实把数据提交给安全框架,用name绑定,然后提交的时候把表达绑定给security框架的内置网页,让他进行验证。<i class="sign-out icon"></i> 注销。springsecurity整合thymeleaf。//开启记住我功能 cookie,默认保存两周。权限控制管理,让用户登录显示用户信息。给这个访问路径,加上角色权限。加了登录验证与角色授予。

qq_53374893的博客 681

解决:org.springframework.security.config.annotation.web.builders.HttpSecurity,spirngboot整合rdeis时遇到的坑

问题: redis与springboot进行整合时遇到的错误,配置链接都没有问题 同时还报了以下错误:找不到类HttpSecurity,和一个不知道什么类加载失败 *------------------------------------------------------------------------------------ 解决方法: 配置没有问题,应该是依赖导入的问题,然而搜索仓库也没找到这个类,于是判断是在导入依赖的时候导致的冲突,或者怀疑之前有误操作 *-------------------

khbilhjknkjb的博客 6052

Spring Security 6.x 系列(7)—— SecurityBuilder 继承链源码分析

`WebSecurity`、`HttpSecurity`、`AuthenticationManagerBuilder` 都是框架中的构建者,把他们放到一起看看他们的共同特点: 可以看出他们都有这样一条相同的继承链: ```bash |- SecurityBuilder |- AbstractSecurityBuilder |- AbstractConfiguredSecurityBuilder

gmHappy 1万+

SpringBoot整合Security安全框架、控制权限

我想每个写项目的人,都肯定会遇到控制权限这个问题. 例如这个这个链接只能管理员访问,那个链接丫只能超级管理员访问等等,实现方式也有多种多样,控制的粒度也不一样。 以前刚学的时候,不会框架,大都是手写注解+过滤器来进行权限的控制,但这样增加了过滤器的负担。用起来也会稍微有些麻烦,粒度不太好控制。 用框架的话,就是封装了更多的操作,让一切更简单吧。当然不局限于Security,还有像Shiro安全框架,这两种非常常见。 一起加油吧!!!???? 先看个图舒缓一下,准备开始吧????‍???? 下面就开始吧!

北 2875

12、构建安全的响应式 Web 应用与 Spring Security 实践

本文介绍了如何构建一个安全的响应式 Web 应用,涵盖使用 Spring Security 实现用户认证、授权、注销和注册等功能。详细讲解了响应式数据库操作、WebClient 调用、测试响应式端点、内存认证与数据库认证的实现,以及自定义安全配置和密码编码的最佳实践。通过这些内容,开发者可以掌握构建安全响应式博客系统的核心技术。

moss5的博客 54

【扫地机器人】详细介绍扫地机器人软硬件测试和场景化测试

本文提出2025版扫地机器人全生命周期测试方案,涵盖实验室仿真、硬件台架、客户实景等全流程验证。测试以"清洁率≥95%、覆盖率≥98%、MTBF≥1000h"为核心指标,采用数字孪生与120套真实场景结合的双V模型。重点包括:传感器精度(LDS误差<±10mm)、清洁系统性能(10g粉尘吸入率≥99%)、动力续航(800次循环容量保持≥80%)等硬件测试;以及SLAM重定位(误差<5cm)、AI识别(mAP>92%)等软件验证。方案特别针对宠物家庭(毛发缠绕率≤3%)、

2501_92897788的博客 2283

spring security-源码流程分析(一)

spring security经常在项目中用到,但是平常只是简单的使用肯定是不够的,我们需要了解深层次的东西,才能在使用的过程中不畏惧,本次打算从demo入手,跟踪源码,剖析security内在 环境 springboot: 2.3.4.RELEASE spring security :spring-boot-starter-security版本跟随springboot 一、springboot默认自动配置了security,我们看下security相关类都是在什么情况下加载的 如上图,securit.

luoxiaomei999的博客 975

高通Camera IFE时钟配置

高通Camera IFE时钟配置中的minHorizontalBlanking和minVerticalBlanking配置计算方法

一个懒癌的驱动工程师的随笔分享 6168

【Spring Security】WebSecurity

首先,查看WebSecurity类图,如下: SecurityBuilder是基础接口,代码如下: public interface SecurityBuilder<O> { /** * Builds the object and returns it or null. * * @return the Object to be built or null if...

be Free & Happy 250

STM32F4_DHT11数字温湿度传感器

开机的时候先检测是否有DHT11存在,如果没有,则提示错误。DHT11和DS18B20相同,传感器输出的都是未编码的二进制数字。本节我们将利用STM32F4来读取DHT11的温湿度传感器,获取环境的温度和湿度值。因此:温湿度的读取方式就是整数部分的二进制转换成十进制放在整数部分;小数部分的二进制转换成十进制放在小数部分。DHT11和MCU的一次通讯时间最大3ms,主机连续向DHT11采样的间隔建议不小于100ms。DHT11是广州奥松有限公司生产的一款温湿度一体化的数字传感器。数据分小数部分和整数部分。

light_2025的博客 3432

KNX智能家居工程设计应用

KNX,是一个起源于欧洲的总线标准,主要应用于家居和楼宇中,对末端电气设备进行总线式的控制,比如照明、空调、地暖、电动窗帘和遮阳设备等等。根据2017年英国著名咨询公司BSRIA的数据报告显示,在中国的智能家居和灯光控制市场,KNX产品的市场份额为各类产品中排名第一,占据了42%的市场份额,远远领先于其他的标准协议。设备中一个继电器表示一路输出,某些功能可能需要用到多个输出,比如1个窗帘AC输出需要占用两路继电器输出,一个继电器用于控制正转,一个用于控制反转,而普通开关输出则需要占用一路继电器输出即可。

hhhh5555666的博客 934

Spring Security 六 WebSecurityConfigurerAdapter

文章目录一、WebSecurityConfigurerAdapter是什么?1.WebSecurityConfigurer是什么?2.WebSecurity2.1 WebSecurity定义2.2 AbstractConfiguredSecurityBuilder2.3二、使用步骤1.引入库2.读入数据总结 一、WebSecurityConfigurerAdapter是什么? WebSecurityConfigurerAdapter是为创建WebSecurityConfigurer实例提供方便的基类,该类允

weixin_43172297的博客 8580

手把手教你用STM32CubeIDE移植Vector CCP驱动,实现与INCA的标定通信(附避坑指南)

本文详细介绍了如何在STM32CubeIDE环境下移植Vector CCP驱动,实现与INCA的标定通信。从开发环境准备、CAN外设配置到CCP协议栈移植和A2L文件生成,提供了完整的操作流程和常见问题解决方案,帮助工程师快速掌握基于CAN总线的标定技术。

weixin_28685287的博客 138

【Spring-Security源码分析】AuthenticationManagerBuilder

1、继承结构类图 AuthenticationManagerBuilder用于创建AuthenticationManager。 允许轻松构建内存身份验证,LDAP身份验证,基于JDBC的身份验证,添加UserDetailsService以及添加AuthenticationProvider。 public interface SecurityBuilder<O> { /*...

通往神秘的道路的专栏 1万+

模式分类识别 | TCN时间卷积神经网络多特征分类预测(Matlab完整程序)

模式分类识别 | TCN时间卷积神经网络多特征分类预测(Matlab完整程序)

前程算法屋的博客 748

华为OD机试 新系统真题 【最小代价完成论文评审】

华为OD机试 新系统真题【最小代价完成论文评审】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【最小代价完成论文评审】多语言题解。

qq_45776114的博客 443

09 - spring security加载流程

Spring Security 加载流程摘要: 核心配置类HttpSecurityConfiguration通过@Bean创建原型作用域的HttpSecurity对象,初始化默认安全配置(CSRF、登录页等)。 SpringBootWebSecurityConfiguration提供默认的SecurityFilterChain Bean,配置基础认证规则(anyRequest().authenticated())。 开发者可通过自定义SecurityFilterChain Bean覆盖默认配置,此时会注入预

shuai的博客 1070

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

spring-security(一)java config加载机制-WebSecurityConfiguration

前言: spring security给我们提供了功能非常强大的安全保护机制,在使用时的配置也极其简单,在和spring boot工程集成的时候,简单到只需要我们用一个注解@EnableWebSecurity就可以把需要的过滤器都配置好,可是这一切是怎么发生的呢?在本系列文章的第一篇就让我们结合源码来一探究竟。 环境: spring boot 版本:1.5.4.RELEASE ...

高枫的博客 2519

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Security配置生效源码分析

文章概述 本文主要解决几个问题: security配置生效的入口是哪里 我们平时写的security配置是如何被调用的 为什么我们写的配置需要继承WebSecurityConfigurerAdapter HttpSecurity和WebSecurity是干嘛用的 配置核心类 启动Security,需要在启动类上添加@EnableSecurity注解 @SpringBootApplication @EnableWebSecurity public class ThingsboardApp {

Xjzzon的博客 996

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Spring Security源码(一)springSecurityFilterChain的创建与运行

整个框架的核心就是构建一个名字为的过滤器Bean,它的类型是。底层通过FilterChainProxy代理去调用各种Filter(Filter链),Filter通过调用完成认证 ,通过调用完成授权。

Instanceztt的博客 2290

SpringBoot Security安全认证框架初始化流程&认证流程之源码分析

以RuoYi-Vue前后端分离版本为例分析SpringBoot Security安全认证框架初始化流程&认证流程的源码分析

老杜的博客 1538

慢慢来就很简单的security学习(四)源码阅读httpSecurity和AuthenticationManager

文章目录httpSecurity 的执行流程和 AuthenticationConfiguration 配置的 AuthenticationManager0x00 回顾0x01 从 WebSecurityConfigurerAdapter 里面的 getHttp() 开始0x02 看一下 AuthenticationConfiguration 里面做了些什么0x03 AuthenticationM...

miyahejuzi的博客 2248

默认SpringSecurity大致启动流程源码分析

默认SpringSecurity大致启动流程源码分析

HHoao的博客 780

珍贵资料:阿里内部Spring Security实战指南,邀您一同开启安全之旅

第1章 给大家简单的介绍Spring Security,创建了一个简单的Spring Security项目,带领大家初步领略Spring Security带来的便利。第2章 我们使用表单认证来保护URL资源。第3章 将更加深入地对Spring Security 进行配置,且初步使用授权机制。在验证用户名和密码之前,引入辅助验证可有效防范暴力试错,图形验证码就是简单且行之有效的一种辅助验证方式。本章将使用过滤器和自定义认证两种方式实现图形验证码功能。第5章 主要讲。

资料免费分享,点击名片 951
上一篇: Spring Security 原理讲解
下一篇: spring security启动流程解析
Hack_Bug
博客等级 码龄15年 34粉丝 25原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值