【深入浅出Spring Security(二)】Spring Security的实现原理

news/2024/11/25 15:49:38/

Spring Security的实现原理

  • 一、实现原理
  • 二、内置Filter以及默认加载的Filter
  • 三、自动配置分析(SpringBootWebSecurityConfiguration)
    • @ConditionalOnMissingBean
  • 四、自己配置SecurityFilterChain

一、实现原理

在 Spring Security 中,认证、授权等功能都是基于过滤器来完成的。开发者所见到的 Spring Security 提供的功能,都是通过这些过滤器来实现的,这些过滤器按照既定的优先级排列,最终形成一个过滤器链。当然,开发者也可以自己定义过滤器,并通过@Order注解去调整自定义过滤器在过滤器链中的位置。

需要注意的是,默认过滤器并不是直接放在 Web 项目的原生过滤器链中(即不是JavaWeb中的filter), 而是通过一个 FilterChainProxy 来统一管理。Spring Security中的过滤器链通过 FilterChainProxy 嵌入到 Web 项目的原生过滤器链中

在这里插入图片描述
在 Spring Security 中,像上图中嵌入的过滤链不仅仅只有一个,可能会有多个,当存在多个过滤器链时,多个过滤器链之间要指定优先级,当请求到达后,会从 FilterChainProxy 进行分发,先和哪个过滤器链匹配上,就用哪个过滤器链进行处理。当系统中存在多个不同的认证体系时,那么使用多个过滤器链就非常有效。

在这里插入图片描述
FilterChainProxy 作为一个顶层管理者,将统一管理 Security Filter。FilterChainProxy 本身将通过 Spring 框架提供的 DelegatingFilterProxy 整合到原生过滤器链中。

在这里插入图片描述

二、内置Filter以及默认加载的Filter

下面表格是默认加载的 Filter(这里的 Filter 都不是原始的 Web Filter),加载顺序是按下表从上而下进行的。

默认加载Filter过滤器作用是否加载
WebAsyncManagerIntegrationFilter将 WebAsyncManager 与SpringSecurity上下文集成YES
SecurityContextPersistenceFilter在处理请求之前,将安全信息加载到SecurityContextHolder中YES
HeaderWriterFilter处理头信息加入响应中YES
CsrfFilter处理CSRF攻击YES
LogoutFilter处理注销登录YES
UsernamePasswordAuthenticationFilter处理表单认证YES
DefaultLoginPageGeneratingFilter配置默认登录页面YES
DefaultLogoutPageGeneratingFilter配置默认注销页面YES
BasicAuthenticationFilter处理 HttpBasic 登录YES
RequestCacheAwareFilter处理请求缓存YES
SecurityContextHolderAwareRequestFilter包装原始请求YES
AnoymousAuthenticationFilter配置匿名认证YES
SessionManagementFilter处理Session并发问题YES
ExceptionTraslationFilter处理认证/授权中的异常YES

加载顺序和上面表一致,通过调试也可以发现(其中第一个不属于内置的Filter,而是自定义的,用来禁用URL进行编码,而最后一个是拦截器并非过滤器,剩下的与上表对应):

在这里插入图片描述

下面俩图总结了默认加载的和未默认加载的Spring Security中的过滤器。
在这里插入图片描述
在这里插入图片描述可以看出,Spring Security 提供了 30 多个过滤器。默认情况下 Spring Boot 在对 Spring Security 进行自动化配置时(SpringBoot Auto Configuration),会创建一个名为 SpringSecurityFilterChain 的过滤器链对象,并注入到 Spring 容器中,这个过滤器链将负责所有的安全管理,包括用户认证、授权、重定向到登录页面等。

三、自动配置分析(SpringBootWebSecurityConfiguration)

下面 SecurityFilterChain 自动配置的具体含义:让所有资源都必须经过认证,通过表单和Basic认证。

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
class SpringBootWebSecurityConfiguration {/*
如果用户指定他们自己的WebSecurityConfigurerAdapter
或SecurityFilterChain bean,这将完全取消
,并且用户应该指定他们想要配置的所有位作为自定义安全配置的一部分。
*/@Configuration(proxyBeanMethods = false)@ConditionalOnDefaultWebSecuritystatic class SecurityFilterChainConfiguration {@Bean@Order(SecurityProperties.BASIC_AUTH_ORDER)SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated();// 这表示所有请求都必须认证http.formLogin();// 开启表单认证http.httpBasic();// 开启basic认证return http.build();}}/*** Configures the {@link ErrorPageSecurityFilter}.*/@Configuration(proxyBeanMethods = false)@ConditionalOnClass(WebInvocationPrivilegeEvaluator.class)@ConditionalOnBean(WebInvocationPrivilegeEvaluator.class)static class ErrorPageSecurityFilterConfiguration {@BeanFilterRegistrationBean<ErrorPageSecurityFilter> errorPageSecurityFilter(ApplicationContext context) {FilterRegistrationBean<ErrorPageSecurityFilter> registration = new FilterRegistrationBean<>(new ErrorPageSecurityFilter(context));registration.setDispatcherTypes(DispatcherType.ERROR);return registration;}}@Configuration(proxyBeanMethods = false)@ConditionalOnMissingBean(name = BeanIds.SPRING_SECURITY_FILTER_CHAIN)@ConditionalOnClass(EnableWebSecurity.class)@EnableWebSecuritystatic class WebSecurityEnablerConfiguration {}}

如果用户指定了他们自己的配置,那这个 SecurityFilterChain 配置就会按用户指定的来。

@ConditionalOnMissingBean

实现效果是源于 SpringBoot 内的 @ConditionalOnMissingBean 注解,用于根据是否存在指定类型的Bean来决定是否创建或注册一个Bean。如果存在指定类型的Bean,则不会创建或注册该Bean;否则,会创建或注册该Bean。

@ConditionalOnDefaultWebSecurity =》
元注解 @Conditional(DefaultWebSecurityCondition.class) =》

@ConditionalOnClass({ SecurityFilterChain.class, HttpSecurity.class })static class Classes {}@ConditionalOnMissingBean({org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.class,SecurityFilterChain.class })

上述源码表示使用默认配置的条件有俩条:

  1. 类路径得有 SecurityFilterChain 、HttpSecurity (注意是类路径,容器内有对SecurityFilterChain的默认实现类,但没有交给容器管理,所以也是满足条件2的);
  2. 容器内不得有 SecurityFilterChain 和 WebSecurityConfigurerAdapter 实例对象;

即容器中没有 WebSecurityConfigurerAdapter 对象或 SecurityFilterChain 对象,就会按默认配置来,有的话就按用户自定义来。

但是在Spring Security 5.7.8 这个新版本中已经把继承 WebSecurityConfigurerAdapter 这种方式给弃用了,而是去使用@EnableWebSecurity注解。原因是这样可以更加灵活地配置安全策略,并且能够更好地与Spring Boot等框架进行集成。比如使用 @EnableGlobalMethodSecurity 注解进行进一步的安全配置。

四、自己配置SecurityFilterChain

在 5.7.8 之后已经开始推荐使用 @EnableWebSecurity 注解的形式进行开发了,而 WebSecurityConfigurerAdapter 这个类已经被弃用。新版配置如下:

@EnableWebSecurity
public class WebSecurityConfig {@Beanpublic SecurityFilterChain securityFilterChain(@Autowired HttpSecurity http) throws Exception {return http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().build();}}

注意:可以不用在写@Configuration注解去表明这是配置类了,这是因为@EnableWebSecurity 上被@Configuration 元注解标识了。

在这里插入图片描述


http://www.ppmy.cn/news/101687.html

相关文章

vue+elementUI表格某一行修改局部刷新实现

log: 使用elementUI表格&#xff0c;想修改某一行数据然后不想全量刷新&#xff0c;只想刷新当前修改的行内容 实现过程&#xff1a; 表格操作列代码&#xff1a; 1.主要是获取下标和行内容&#xff1a;scope.$index,scope.row <el-table-column width"200" …

一个完整的APP定制开发流程是怎样的?

随着移动互联网的发展&#xff0c;越来越多的 APP应用软件进入人们的生活&#xff0c;让我们的生活更便捷、更舒适。而随着互联网技术的进步&#xff0c;移动互联网应用软件开发行业也越来越成熟&#xff0c;为了适应市场需求&#xff0c;各种功能强大、性能良好的 APP应用软件…

swagger-codegen的使用方法及常见参数配置

前言 在进行API开发时&#xff0c;我们通常需要定义API的接口规范和文档&#xff0c;以方便其他开发者调用和使用。Swagger是一款非常流行的API文档生成工具&#xff0c;它可以帮助我们快速生成API接口文档&#xff0c;并提供了许多便捷的功能。本文将介绍如何使用swagger-cod…

MYSQL 查询数据库中所有表中的数据量

1. 查询数据库中所有表中的数据量 SELECT TABLE_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA your_database_name; 将 your_database_name 替换为您实际使用的数据库名称。 执行以上查询语句后&#xff0c;将会获取到 your_database_name 数据库…

jQuery-表中数据的添加与删除

<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>表中数据的添加与删除</title> <link rel"stylesheet" type"text/css&quo…

数据仓库的数据组织形式与技术实现

随着信息时代的到来&#xff0c;数据成为越来越重要的资源。数据仓库作为一种企业级的数据存储和管理架构&#xff0c;在信息管理中扮演着重要的角色。数据仓库的组织形式直接影响到数据的有效性和可靠性。本文将重点探讨数据仓库的数据组织形式&#xff0c;以及其优缺点和未来…

使用uniapp开发国际化---app,vue,nvue

插件市场下载示例 hello-i18n 示例工程 - DCloud 插件市场 项目使用 main.js引入 // 国际化 json 文件&#xff0c;文件内容详见下面的示例 import en from ./en.json import zhHans from ./zh-Hans.json import zhHant from ./zh-Hant.json const messages {en,zh-Hans: …

TCP协议的RST标志

下文中的内容多数来自【参考】中的文章&#xff0c;这边进行一个整理和总结&#xff0c;后续会慢慢增加出现各个 RST 包的测试代码&#xff0c;便于理解。 TCP的 “断开连接” 标志 RST 标志 Reset&#xff0c;复位标志&#xff0c;用于非正常地关闭连接。它是 TCP 协议首部里…