Spring 整合 Spring Security
本文最后更新于:2024年9月8日 晚上
Spring 整合 Spring Security
简介
- Spring Security 是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,可以实现强大的Web安全控制,对于安全控制,仅需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理。
- Spring Security的两个主要目标。
- 认证(Authentication)
- 身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。
- 身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。
- 授权(Authorization)
- 授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。
- 这个概念是通用的,而不是只在Spring Security 中存在。
- 认证(Authentication)
过滤器
- Spring Security 基本都是通过过滤器来完成配置的身份认证,权限认证以及登出。
- Spring Security 在 Servlet 的过滤链(filter chain)中注册了一个过滤器
FilterChainProxy
,它会把请求代理到 Spring Security 自己维护的多个过滤链,每个过滤链会匹配一些 URL,如果匹配则执行对应的过滤器,过滤链是有顺序的,一个请求只会执行第一条匹配的过滤链,Spring Security 的配置本质上就是新增,删除,修改过滤器。 - 默认情况下系统帮我们注入的这 15 个过滤器,分别对应配置不同的需求,例如
UsernamePasswordAuthenticationFilter
是用来使用用户名和密码登录认证的过滤器,但是很多情况下登录不止是简单的用户名和密码,又可能是用到第三方授权登录,这个时候我们就需要使用自定义过滤器。
1 |
|
核心类
SecurityContextHolder
SecurityContextHolder
存储SecurityContext
对象,SecurityContextHolder
是一个存储代理,有三种存储模式分别是:- MODE_THREADLOCAL:SecurityContext 存储在线程中。
- MODE_INHERITABLETHREADLOCAL:
SecurityContext
存储在线程中,但子线程可以获取到父线程中的SecurityContext
- MODE_GLOBAL:
SecurityContext
在所有线程中都相同。
SecurityContextHolder
默认使用 MODE_THREADLOCAL 模式,SecurityContext
存储在当前线程中,调用SecurityContextHolder
时不需要显示的参数传递,在当前线程中可以直接获取到SecurityContextHolder
对象。
1 |
|
Authentication
Authentication
即验证,表明当前用户是谁,什么是验证,比如一组用户名和密码就是验证,当然错误的用户名和密码也是验证,只不过 Spring Security 会校验失败。
1 |
|
AuthenticationManager/ProviderManager/AuthenticationProvider
- 其实这三者很好区分,
AuthenticationManager
主要就是为了完成身份认证流程,ProviderManager
是AuthenticationManager
接口的具体实现类,ProviderManager
里面有个记录AuthenticationProvider
对象的集合属性providers
,AuthenticationProvider
接口类里有两个方法。
1 |
|
- 接下来就是遍历
ProviderManager
里面的providers
集合,找到和合适的AuthenticationProvider
完成身份认证。
UserDetailsService/UserDetails
UserDetail
是Spring Security中的用户实体类。- 在
UserDetailsService
接口中只有一个简单的方法。
1 |
|
身份认证流程
- 在运行到
UsernamePasswordAuthenticationFilter
过滤器的时候首先是进入其父类AbstractAuthenticationProcessingFilter
的doFilter()
方法中。
1 |
|
AbstractAuthenticationProcessingFilter
调用UsernamePasswordAuthenticationFilter
的attemptAuthentication()
方法完成身份认证。
1 |
|
- 通过
AuthenticationManager
接口实现类ProviderManager
来遍历得到Provider,调用对应的authenticate()
方法。
1 |
|
- 调用Provider的
authenticate()
方法。- 例如Provider为
DaoAuthenticationProvider
继承自AbstractUserDetailsAuthenticationProvider
,后者实现了AuthenticationProvider
接口,所以调用的是AbstractUserDetailsAuthenticationProvider
的authenticate()
方法。
- 例如Provider为
1 |
|
-
接下来我们来看下
DaoAuthenticationProvider
里面的三个重要的方法。-
additionalAuthenticationChecks:定义比对方式。
-
retrieveUser:获取需要比对的
UserDetails
对象。 -
createSuccessAuthentication:生产最终返回
Authentication
的方法。
-
1 |
|
pom.xml
1 |
|
配置
基础配置类
@EnableWebSecurity
:开启WebSecurity模式。
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!