SpringSecurity6从入门到上天系列第六篇:解决这个问题为什么在引入SpringSecurity之后所有的请求都需要先做登录认证才可以进行访问呢

news2024/11/24 19:42:55

文章目录

问题引入

1:问题阐述

2:问题分析

一:从SpringBoot的自动装配

1:@SpringBootApplication介绍

2:自动装配的核心方法

3:核心方法的调用路径

4:SpringSecurity核心配置

5:SpringBoot...Configuration详解

6:总结一下


大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。

孙哥链接:孙哥个人主页
作者简介:一个颜值99分,只比孙哥差一点的程序员
本专栏简介:话不多说,让我们一起干翻SpringSecurity6

本文章简介:话不多说,让我们讲清楚SpringSecurity6中为什么在引入SpringSecurity之后所有的请求都需要先做登录认证才可以进行访问呢

问题引入

1:问题阐述

        为什么在引入SpringSecurity之后所有的请求都需要先做登录认证才可以进行访问呢?

2:问题分析

        分析清楚这个问题之前,我们先从自动装配开始研究。

一:从SpringBoot的自动装配

1:@SpringBootApplication介绍

        这个注解的作用就是标志这个类是SpringBootApplication的启动类。

@SpringBootApplication
public class BigtreeApplication {
	public static void main(String[] args) {
		SpringApplication.run(BigtreeApplication.class, args);
	}
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    @AliasFor(annotation = EnableAutoConfiguration.class)
    Class<?>[] exclude() default {};

    @AliasFor(annotation = EnableAutoConfiguration.class)
    String[] excludeName() default {};

    @AliasFor(annotation = ComponentScan.class,attribute = "basePackages")
    String[] scanBasePackages() default {};

    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(annotation = ComponentScan.class,attribute = "nameGenerator")
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor( annotation = Configuration.class)
    boolean proxyBeanMethods() default true;
}

       

        这个注解是一个复合注解@SpringBootConfiguration这个注解的作用带表了这当前这个类是一个SpringBoot配置类,自动交给SpringIOC容器进行管理。

        第二个注解是ComponentScan这个注解的作用是定义Spring的扫描路径的。通畅对应我们自己定义的组件例如:Controller,Service,Dao这些组件。

        第三个注解是:@EnableAutoConfiguration这个注解是SpringBoot自动装配的关键注解,这个注解包含两个核心注解

        第一个注解是:@Import({AutoConfigurationImportSelector.class})这个注解的作用就是在导入当前类的同时顺便导入AutoConfigurationImportSelector这个类也加载进来。

2:自动装配的核心方法

org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations	
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
			.getCandidates();
		Assert.notEmpty(configurations,
				"No auto configuration classes found in "
						+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}
org.springframework.boot.context.annotation.ImportCandidates	
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
		Assert.notNull(annotation, "'annotation' must not be null");
		ClassLoader classLoaderToUse = decideClassloader(classLoader);
		String location = String.format(LOCATION, annotation.getName());
		Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
		List<String> importCandidates = new ArrayList<>();
		while (urls.hasMoreElements()) {
			URL url = urls.nextElement();
			importCandidates.addAll(readCandidateConfigurations(url));
		}
		return new ImportCandidates(importCandidates);
	}

        此方法执行完毕的返回值:

        这个配置在:spring-boot-autoconfigure-3.0.12.jar包下!\META-INF\spring\包下的

        org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中,这里边就是Spring中的各种需要自动装配的组件。其中就有很多的配置组件。

3:核心方法的调用路径

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
	  at org.springframework.boot.context.annotation.ImportCandidates.load(ImportCandidates.java:90)
	  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:180)
	  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:126)
	  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:430)
	  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:796)
	  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:726)
	  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:697)
	  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:182)
	  at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:415)
	  at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:287)
	  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344)
	  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)
	  at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:779)
	  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
	  - locked <0x12a7> (a java.lang.Object)
	  at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733)
	  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
	  at com.dashu.AlibabaApplication.main(AlibabaApplication.java:10)

        这个调用路径是怎么获得的?方法很简单,只需要在这个核心方法的中间打上一个断点。

        然后我们启动main方法,等线程执行过这个方法的断点。然后我们在idea上玩一个骚操作就可以了。

        然后,我们在debug区域,找到最上层一个方法,然后我们右键Exports Thread即可。 

4:SpringSecurity核心配置

org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(DefaultAuthenticationEventPublisher.class)
@EnableConfigurationProperties(SecurityProperties.class)
@Import({ SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class })
public class SecurityAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
	public DefaultAuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher publisher) {
		return new DefaultAuthenticationEventPublisher(publisher);
	}

}

        然后,就会加载这两个组件:SpringBootWebSecurityConfiguration.class, SecurityDataConfiguration.class 尤其是第一个。

5:SpringBoot...Configuration详解

        这里边只有一个@Bean注解,最终会创建一个对象:SecurityFilterChain,为什么最终引入了SpringSecurity依赖之后就会所有的请求都会被拦截答案就在这个方法里边。

		@Bean
		@Order(SecurityProperties.BASIC_AUTH_ORDER)
		SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
            //任意Http请求都会被认证拦截
			http.authorizeHttpRequests().anyRequest().authenticated();
            //认证的时候支持form表单认证
			http.formLogin();
            //http的basic认证
			http.httpBasic();
			return http.build();
		}
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {


	@Configuration(proxyBeanMethods = false)
	@ConditionalOnDefaultWebSecurity
	static class SecurityFilterChainConfiguration {

		@Bean
		@Order(SecurityProperties.BASIC_AUTH_ORDER)
		SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
			http.authorizeHttpRequests().anyRequest().authenticated();
			http.formLogin();
			http.httpBasic();
			return http.build();
		}

	}


	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)
	@ConditionalOnClass(EnableWebSecurity.class)
	@EnableWebSecurity
	static class WebSecurityEnablerConfiguration {

	}

}

6:总结一下

        基于SpringBoot的自动装配,由于SpringSecurity的装配配置在SpringBoot配置环境中,所以它默认会被加载,加载完毕之后defaultSecurityFilterChain被调用,SecurityFilterChain对象被创创建。所有的方法都会被被鉴权。

        具体的方法调用路径或者叫配置路径是这样的:首先是三个核心的注解:

@SpringBootApplication-> @EnableAutoConfiguration>@Import(AutoConfigurationImportSelector)

       这样的代码就会基于下面这个调用路径:

"main@1" prio=5 tid=0x1 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
	  at org.springframework.boot.context.annotation.ImportCandidates.load(ImportCandidates.java:90)
	  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getCandidateConfigurations(AutoConfigurationImportSelector.java:180)
	  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.getAutoConfigurationEntry(AutoConfigurationImportSelector.java:126)
	  at org.springframework.boot.autoconfigure.AutoConfigurationImportSelector$AutoConfigurationGroup.process(AutoConfigurationImportSelector.java:430)
	  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGrouping.getImports(ConfigurationClassParser.java:796)
	  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorGroupingHandler.processGroupImports(ConfigurationClassParser.java:726)
	  at org.springframework.context.annotation.ConfigurationClassParser$DeferredImportSelectorHandler.process(ConfigurationClassParser.java:697)
	  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:182)
	  at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:415)
	  at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:287)
	  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344)
	  at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)
	  at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:779)
	  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:597)
	  - locked <0x12a7> (a java.lang.Object)
	  at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	  at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:733)
	  at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:435)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
	  at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290)
	  at com.dashu.AlibabaApplication.main(AlibabaApplication.java:10)

        调用到这个方法里边:AutoConfigurationImportSelector#getCandidateConfigurations最后查到核心组件的配置文件。这样加载到SpringSecurity的核心文件。最终调用到上边的方法,导致所有的方法都得进行登录认证。

二:默认认证方式的条件限制

1:@ConditionalOnDefaultWebSecurity

        此注解显示了要想使用下面SpringSecurity的默认认证方式是有条件的。

        也就是说,并不是所有的Http请求都必须走默认认证。进入这个注解:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(DefaultWebSecurityCondition.class)
public @interface ConditionalOnDefaultWebSecurity {

}

        这个注解上边还有一个注解:@Conditional(DefaultWebSecurityCondition.class)

class DefaultWebSecurityCondition extends AllNestedConditions {

	DefaultWebSecurityCondition() {
		super(ConfigurationPhase.REGISTER_BEAN);
	}

	@ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })
	static class Classes {

	}

	@ConditionalOnMissingBean({ SecurityFilterChain.class })
	static class Beans {

	}

}

        在这个类当中我们定义了两种鉴权规则。第一种是基于Class,他是基于类作用,也就是说当前在classpath下如果有上述两个class的话,就可以走默认的认证方式。在SpringSecurity中肯定是有的,这也就是在引入SpringSecurity依赖之后就会走默认的配置。

        第二种是基于丢失Bean的情况,如果丢失了,那么我们可以走默认的认证规则了。也就是说,如果没有了SecurityFilterChain这个对象的话,那么就不在使用默认的认证规则了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1214169.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PMP备考短期极限上岸攻略!

作为一位通过PMP考试成功上岸的3A人士&#xff0c;下面的文章包含了所有PMP考试的实用知识&#xff0c;是一本适合初学者的PMP备考攻略手册。如果你有意向了解或者报考PMP考试&#xff0c;这篇文章肯定会对你有很大的帮助&#xff01; 对于新手第一个需要知道的就是PMP是什么&…

【python】—— 控制语句和组合数据类型(其一)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

Flume(一)【Flume 概述】

前言 今天实在不知道学点什么好了&#xff0c;早上学了3个多小时的 Flink &#xff0c;整天只学一门技术是很容易丧失兴趣的。那就学点新的东西 Flume&#xff0c;虽然 Kafka 还没学完&#xff0c;但是大数据生态圈的基础组件也基本就剩这倆了。 Flume 概述 生产环境中的数据一…

Sql Prompt 10下载安装图文教程

在操作过程中&#xff0c;请暂时关闭你的防病毒软件&#xff0c;以免其误报导致操作失败。 资源 SQL Prompt 10 https://www.aliyundrive.com/s/QuMWkvE1Sv6 点击链接保存&#xff0c;或者复制本段内容&#xff0c;打开「阿里云盘」APP &#xff0c;无需下载极速在线查看&…

20 - 欲知JVM调优先了解JVM内存模型

从今天开始&#xff0c;我将和你一起探讨 Java 虚拟机&#xff08;JVM&#xff09;的性能调优。JVM 算是面试中的高频问题了&#xff0c;通常情况下总会有人问到&#xff1a;请你讲解下 JVM 的内存模型&#xff0c;JVM 的性能调优做过吗&#xff1f; 1、为什么 JVM 在 Java 中…

Qt高级--(2)自定义标题栏

自定义标题栏 功能点 1.标题栏中最外层布局器使用水平布局器。 2.导航按钮、工具按钮和窗口功能按钮都是用水平布局器&#xff0c;边距和间隔可根据实际情况设置。 3.编写 QSS 样式&#xff0c;并将样式设置到窗口控件中。 4.实现最小化、最大化和关闭窗口按钮功能。 5.实现鼠…

mysql数据库,sql语句中连接查询,连表查询,内连接,外连接,左外连接,右外连接,inner join、left join、right join,全连接

连表查询 现有多张表&#xff1a;员工表 emp&#xff08;员工编号、姓名、工资、部门号、经理编号&#xff09;、部门表 dept&#xff08;部门号、部门名称、部门位置&#xff09;、工资等级表 salgrade&#xff08;等级、工资下限、工资上限&#xff09; 连接查询&#xff1a;…

ClassLoader

Java /Android 默认ClassLoader是PathClassLoader Android 的 PathClassLoader 和DexClassLoader 都是BaseDexClassLoader的子类 BaseClassLoader是ClassLoader的子类,通过loadClass方法加载,Android将Java的ClassLoader简化了,第二个参数arg2 无效 loadClass 通过 findLoad…

搭建知识付费系统的最佳实践是什么

在数字化时代&#xff0c;搭建一个高效且用户友好的知识付费系统是许多创业者和内容创作者追求的目标。本文将介绍一些搭建知识付费系统的最佳实践&#xff0c;同时提供一些基本的技术代码示例&#xff0c;以帮助你快速入门。 1. 选择合适的技术栈&#xff1a; 搭建知识付费…

YOLO目标检测——烟叶病害检测数据集下载分享【含对应voc、coco和yolo三种格式标签】

实际项目应用&#xff1a;烟叶病虫害防治数据集说明&#xff1a;烟叶病害检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;类别分为&#xff1a;轻度病虫、中度病虫、高度病虫标签说明&#xff1a;使用lableimg标注软件标注&#xff0c;标…

微信群BUG大揭秘!开启身份切换神器

前言 最近微信群里出现了一个神秘的BUG&#xff0c;普通群成员竟然可以艾特全体成员。今天&#xff0c;就让我们一起揭秘这个令人震惊的微信群普通成员可全体成员的BUG 复现步骤 复现步骤也很简单&#xff0c;前提条件就是要在PC客户端操作&#xff01;首先得有个属于自己的群…

OCR文字识别标注小助手

目录 背景 工具界面 操作 1、选择目录 2、更改为正确的信息 3、保存 4、说明 项目 代码 下载 背景 为什么要写这么一个小工具呢&#xff1f;因为要对文字进行标注。 为什么对文字进行标注呢&#xff1f;因为要重新训练识别。 为什么要重新训练识别呢&#xff1f;因…

python socket编程2 - socket创建发送方所需参数的获得

使用socket进行进程间通信或者跨网络的计算机间通讯&#xff0c;有点类似日常生活中的发送快递。 根据发送方的需要&#xff0c;选择不同的物流公司&#xff1a; 在选择适合的公司和运输方式后&#xff0c;需要在app上做出选择&#xff0c;并根据要求填写一些信息。app会根据…

根据视频编码时间批量重命名视频文件

整理收藏的小视频的时候发现很多视频命名很随意&#xff0c;自己命名又太麻烦&#xff0c;看着乱糟糟的文件又心烦&#xff0c;所有写了这个程序&#xff0c;代码如下&#xff1a; import osfrom filetype import filetype from pymediainfo import MediaInfovideo_extension …

【文件读取/包含】任意文件读取漏洞 afr_3

1.1漏洞描述 漏洞名称任意文件读取漏洞 afr_3漏洞类型文件读取/包含漏洞等级⭐⭐⭐⭐⭐漏洞环境docker攻击方式 1.2漏洞等级 高危 1.3影响版本 暂无 1.4漏洞复现 1.4.1.基础环境 靶场docker工具BurpSuite 1.4.2.环境搭建 1.创建docker-compose.yml文件 version: 3.2 servi…

从CentOS向KeyarchOS操作系统的wordpress应用迁移实战

文章目录 从CentOS向KeyarchOS操作系统的wordpress应用迁移实战一、使用浪潮信息X2Keyarch迁移工具完成操作系统的迁移1.1 迁移前的验证1.2 执行迁移评估1.3 开始迁移1.4 验证迁移结果1.5 迁移后的验证 二、总结 从CentOS向KeyarchOS操作系统的wordpress应用迁移实战 CentOS是一…

mysql操作 sql语句中的完整性约束有哪些,主键约束、外键约束、引用完整性约束,主键外键、唯一性

什么是约束&#xff1a;约束&#xff1a;就是约定哪些东西能填、怎么填&#xff1f;哪些东西不能填&#xff1f; 文章目录 前言&#xff1a;建表正文一、实体完整性约束1. 主键约束2. 唯一性约束3. 自增长约束4. 联合主键约束 二、域完整性约束三、引用完整性约束1. 外键约束 讲…

【Git企业开发】第七节.多人协作开发

文章目录 前言 一、多人协作开发 1.1 多人协作一 1.2 多人协作二 1.3 远程分支删除后&#xff0c;本地 git branch -a 依然能看到的解决办法 总结 前言 一、多人协作开发 1.1 多人协作一 目前&#xff0c;我们所完成的工作如下: 基本完成Git的所有本地库的相关操作&#xff0…

未来10年,NAND 与DRAM依然是存储主角

根据Yole Group调查机构的数据显示&#xff0c;在2022年独立记忆体&#xff08;Stand-alone Memory&#xff09;整体市场达到了1440亿美元。其中DRAM占比55.4%&#xff0c;NAND占比40.8%。剩下的NOR、(NV)SRAM/FRAM、EEPROM、新型非易失存储(PCM, ReRAM and STT-MRAM)等占比3.8…

蓝桥杯 string

string简介 string是C标准库的重要组成部分&#xff0c;主要用于字符串处理。 使用string库需要在头文件中包括该库 #include< string> string与char[]不同&#xff0c;string实现了高度的封装&#xff0c;可以很方便地完 成各种字符串的操作&#xff0c;比如拼接、截取…