写在前面

第一节中,我们基本上就引入SpringSecurity依赖,其他什么都没做就完成了认证功能。

之所以我们不用做什么,是因为SpringSecurity默认实现了很多功能。

当然了,这里默认实现都是基于内存的用户认证,即用户都是创建在内存当中的,实际应用都是基于数据库的。

小伙伴们不用着急,只要我们理解了基于内存的用户认证,那基于数据库也是一样的原理,不同的只是一个从内存中获取用户信息,一个从数据库中获取用户信息而已。

接下来,我们来简单看看其基本原理。

一、官方文档

官方文档对SpringSecurity 实现原理其实写的挺详细了。感兴趣的小伙伴可以点下面链接查看

https://docs.spring.io/spring-security/reference/servlet/architecture.html

但对于不少初学者,看官方文档可能会比较吃力。

所以晓凡将其简化,请接着往下看.

二、原理初探

我们以上一篇文章中案例,来看一下SpringSecurity流程。

SpringSecurity的原理其实就是一个过滤器链,如下图所示,每个过滤器各司其职。

上图中,并没有将所有过滤器都例举出来,刚开始,也没必要了解所有过滤器。

下面,我们来看看这几个主要过滤器

UsernamePasswordAuthenticationFilter

这个过滤器处理用户登录的请求。

就像是保安检查你的门禁卡和密码,确认你是不是小区的合法居民。

ExceptionTranslationFilter

这个过滤器捕获安全相关的异常,并将其转换为HTTP响应。

就像是保安发现了问题,他会采取相应的措施,比如不让你进入或者给你一个警告信息。

FilterSecurityInterceptor

这个过滤器是授权的核心,它决定用户是否有权限执行特定的请求。

就像是保安检查你有没有权限去某个特定的区域。

三、 DefaultSecurityFilterChain

为啥SpringSecurity默认帮我们实现那么多,其实主要是DefaultSecurityFilterChain的功劳,它加载了默认的15个Filter。

① 我们在源码中找到DefaultSecurityFilterChain 类,并如下图所示加上断点看一下

② 程序启动后,默认加载15个过滤器

四、各个过滤器作用

这里将例举出15个过滤器的作用,小伙伴们简单了解即可,切忌死记硬背,用得多了自然就记住了

过滤器 作用
DisableEncodeUrlFilter 用来禁用URL编码。有时候,为了防止CSRF攻击,Spring Security会对重定向的URL进行编码。但如果你确定你的应用环境是安全的,可以用这个过滤器来禁用这个功能。
WebAsyncManagerIntegrationFilter 确保异步请求也能正确处理安全上下文。就像是小区保安需要确保即使是快递或者外卖这样的非正常访问,也能被正确地记录和管理。
SecurityContextHolderFilter 确保每个请求都能正确地获取到安全上下文,也就是知道当前是谁在访问。就像是小区保安需要知道是谁在小区里。
HeaderWriterFilter 会在HTTP响应中添加一些安全相关的头部,比如防止XSS攻击的头部。就像是小区保安会在小区的围墙上安装一些安全设备。
CsrfFilter 防止跨站请求伪造攻击,确保用户的操作是他们自己发起的。就像是小区保安会检查每个人的出入证,确保他们不是被坏人操控。
LogoutFilter 处理用户注销的请求,清除用户的身份信息。就像是小区保安在居民离开时,会注销他们的临时通行证。
UsernamePasswordAuthenticationFilter 处理基于用户名和密码的登录请求。就像是小区保安检查居民的门禁卡和密码。
DefaultLoginPageGeneratingFilter 在需要时生成默认的登录页面。就像是小区保安会给没有门禁卡的访客一个标准的表格来填写信息。
DefaultLogoutPageGeneratingFilter 在需要时生成默认的注销页面。就像是小区保安会给需要离开的居民一个标准的流程来完成注销。
BasicAuthenticationFilter 处理基本的身份验证,也就是基于用户名和密码的认证,但不加密。就像是小区保安检查居民的未加密的门禁卡和密码。
RequestCacheAwareFilter 记住用户最初的请求,如果因为认证被重定向,认证成功后可以回到最初的页面。就像是小区保安记得你最初想去的地方,即使你需要去验证身份,回来后他还能指引你去那里。
SecurityContextHolderAwareRequestFilter 确保每个请求都能正确地访问到安全上下文。就像是小区保安确保每个访客都能被正确地记录和管理。
AnonymousAuthenticationFilter 为匿名用户创建一个认证 token。就像是小区保安会给没有门禁卡的访客一个临时的通行证。
ExceptionTranslationFilter 捕获安全相关的异常,并将其转换为HTTP响应,比如401未授权或403禁止访问。就像是小区保安在发现问题时,会采取相应的措施,比如不让进入或者给出一个错误信息。
AuthorizationFilter 负责检查用户是否有权限执行特定的请求。就像是小区保安会检查你有没有权限去某个特定的区域。

五、基于内存的用户认证

在上面流程图中,我们提到了UsernamePasswordAuthenticationFilter 这个过滤器。用户认证就是在这个过滤器中完成的。

这个过滤器的职责就是:将内存中的用户信息获取出来,再和我们界面上输入的用户名和密码进行比较。

如果比较成功,认证成功,允许用户访问资源;如果比较失败,用户认证失败,拒绝访问。

5.1 认证流程

  1. 用户提交登录请求:用户在登录页面输入用户名和密码,然后提交给服务器。
  2. UsernamePasswordAuthenticationFilter拦截用户请求:这个过滤器会拦截登录请求,从请求中提取用户名和密码,创建一个UsernamePasswordAuthenticationToken对象。
  3. AuthenticationManager处理认证UsernamePasswordAuthenticationFilterUsernamePasswordAuthenticationToken传递给AuthenticationManager进行认证。
  4. ProviderManager遍历AuthenticationProviderAuthenticationManager的默认实现ProviderManager会遍历所有的AuthenticationProvider,找到能够处理UsernamePasswordAuthenticationTokenDaoAuthenticationProvider
  5. DaoAuthenticationProvider认证DaoAuthenticationProvider会调用UserDetailsServiceloadUserByUsername方法获取用户信息,然后使用PasswordEncoder对比密码。
  6. 认证成功或失败
    • 如果密码正确,DaoAuthenticationProvider会创建一个新的Authentication对象,包含用户的权限信息,返回给AuthenticationManager
    • 如果密码不正确,会抛出BadCredentialsException异常。
  7. SecurityContextHolder设置认证信息:认证成功后,AuthenticationManager会将认证信息设置到SecurityContextHolder中。
  8. 用户登录成功:用户登录成功后,就可以访问系统资源了。

5.2 代码实现

相信通过上面流程图,大家对认证流程已经很清楚了。

下面我们看看怎么把用户存入内存中,我们参照官方给出的实例即可

https://docs.spring.io/spring-security/reference/servlet/configuration/java.html

①创建一个WebSecurityConfig配置类:

②然后定义一个@Bean,类型是UserDetailsService,实现是InMemoryUserDetailsManager

具体代码如下

@Configuration  //标明这个类为配置类,spring应用程序一启动,类中的been 就会被初始化在spring容器中
@EnableWebSecurity //开启spring security 自定义配置
public class WebSecurityConfig { @Bean
public UserDetailsService userDetailsService(){ //1、创建基于内存的用户管理器
InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
// 3、将第二步创建的UserDetail对象交给UserDetailsManager 管理
inMemoryUserDetailsManager.createUser(
//2、创建UserDetail 对象,用于管理用户名、用户密码、用户角色、用户权限
//下面代码创建了一个用户名为user,密码为123456,角色为user的用户对象
User.withDefaultPasswordEncoder()
.username("user")
.password("123456")
.roles("user")
.build());
return inMemoryUserDetailsManager;
}
}

通过上面配置类,在程序启动的时候。就会将用户名:user 密码:123456 角色:user这样一个用户存入内存中。

当用户想要获取资源时,就会走5.1小节认证流程。

六、小结

通过这篇的学习,我们知道了SpringSecurity 默认为我们干了些啥?基于内存的认证是怎么实现的?

当然了,实际开发中,我们不可能把用户存于内存中,而是需要将用户存于数据库中。通过数据库获取用户和权限信息。

由于文章篇幅原因,这篇就到这儿了。下一篇我们来看看实际开发中,怎么基于数据库进行认证。

SpringBoot3整合SpringSecurity6(二)SpringSecurity默默的干了些啥的更多相关文章

  1. SpringBoot3.0 + SpringSecurity6.0+JWT

    JWT_SpringSecurity SpringBoot3.0 + SpringSecurity6.0+JWT Spring Security 是 Spring 家族中的一个安全管理框架. 一般We ...

  2. Android app启动activity并调用onCreate()方法时都默默地干了什么?

    Android app启动activity并调用onCreate() 方法时都默默地干了什么?   在AndroidManifest.xml文件中的<intent-filter>元素中有这 ...

  3. swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?

    date: 2018-8-01 14:22:17title: swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?description: 阅读 sowft 框架源码, 了解 sowf ...

  4. Netty学习——Netty和Protobuf的整合(二)

    Netty学习——Netty和Protobuf的整合(二) 这程序是有瑕疵的,解码器那里不通用,耦合性太强,有两个很明显的问题,但是要怎么解决呢?如:再加一个内部类型 Person2,之前的代码就不能 ...

  5. Springboot3整合使用ja-captcha行为验证码解决方案

    截止到目前,Springboot最新稳定版本已经迭代到3.0.5,而我们项目中使用的行为验证码框架ja-captcha还没有适配Springboot3,码云上类似的请求也没有得到过回应,于是决定自己动 ...

  6. loadView在App启动时到底都干了些什么?

    loadView在App启动时到底都干了些什么? 查阅苹果官方文档如下: 1. 当你访问一个ViewController的view属性时,如果此时view的值是nil,那么,ViewControlle ...

  7. Beagleboneblack的MLO文件干了些啥

    Beagleboneblack在启动linux之前还有三个启动阶段: ROM code  -->  MLO  -->  u-boot --> kernel 先看看ROM code干了 ...

  8. 输入url后浏览器干了些什么(详解)

    输入url后浏览器干了些什么(详解) DNS(Domain Name System, 域名系统) 解析 DNS解析的过程就是寻找哪台机器上有你真正需要的资源过程.但你在浏览器张红输入一个地址时,例如: ...

  9. 008-shiro与spring web项目整合【二】认证、授权、session管理

    一.认证 1.添加凭证匹配器 添加凭证匹配器实现md5加密校验. 修改applicationContext-shiro.xml: <!-- realm --> <bean id=&q ...

  10. SSM整合学习 二

    二:与Spring MVC整合 一:添加Spring MVC Framework 右键项目名称,点击Add Framework Support 选择Spring-Spring MVC框架 选择Down ...

随机推荐

  1. delphi cxgrid保存正在编辑的行

    procedure SaveGridViewEditing(AView: TcxGridDBTableView); overload; var vDst: TDataSet; begin // 应用未 ...

  2. flutter真机调试出现flutter Launching 'app' on No Devices.

    1. flutter真机调试出现flutter Launching 'app' on No Devices. flutter Launching 'app' on No Devices. 我的是华为手 ...

  3. kubernets学习笔记二

    Kubernetes部署"容器化应用" Kubernetes整体架构 何为"容器化应用"? 通俗点来说,就是你把一个程序放在docker里部署,这个docker ...

  4. Frp内网穿透(一)

    ftp简介 frp frp 是一个可用于内网穿透的高性能的反向代理应用,支持 tcp, udp, http, https协议. 利用处于内网或防火墙后的机器,对外网环境提供 http 或 https ...

  5. 项目中途引入Mybatis-plus后报错,报错Caused by: java.lang.ClassNotFoundException: org.mybatis.logging.LoggerFactory

    一.报错原因 mybatis-plus和pagehelper jar包冲突,注释mybatis-spring和pagehelper插件即可 <!-- SpringBoot集成mybatis框架 ...

  6. Luogu P3899 湖南集训 更为厉害 题解 [ 紫 ] [ 可持久化线段树 ] [ dfs 序 ] [ 线段树合并 ]

    更为厉害:可持久化做法有点意思,但线段树合并做法就很无脑了. 线段树合并做法 显然有三种 \(b\) 的位置的分类讨论. 当 \(b\) 为 \(a\) 的祖先时 从祖先里选 \(b\),从儿子里选 ...

  7. mysql之增删改

    编写配置文件[db.properties]: driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbcStudy?useUni ...

  8. 7. Docker 容器数据卷的使用(超详细的讲解说明)

    7. Docker 容器数据卷的使用(超详细的讲解说明) @ 目录 7. Docker 容器数据卷的使用(超详细的讲解说明) 1. Docker容器数据卷概述 2. Docker 容器数据卷的使用演示 ...

  9. 【FAQ】HarmonyOS SDK 闭源开放能力 —Live View Kit (1)

    1.问题描述: 客户端创建实况窗后,通过Push kit更新实况窗内容,这个过程是自动更新的还是客户端解析push消息数据后填充数据更新?客户端除了接入Push kit和创建实况窗还需要做什么工作? ...

  10. Python类型提示完全指南:用类型安全重构你的代码,提升10倍开发效率

    title: Python类型提示完全指南:用类型安全重构你的代码,提升10倍开发效率 date: 2025/2/23 updated: 2025/2/23 author: cmdragon exce ...