Spring Security 快速入门
Spring Security 快速入门
快速开始
核心 API
设计原理
Spring Security 对于 Servlet 的支持基于过滤链(FilterChain
)实现。
Spring 提供了一个名为 DelegatingFilterProxy
的 Filter
实现,该实现允许在 Servlet 容器的生命周期和 Spring 的 ApplicationContext
之间进行桥接。 Servlet 容器允许使用其自己的标准注册 Filters,但它不了解 Spring 定义的 Bean。 DelegatingFilterProxy
可以通过标准的 Servlet 容器机制进行注册,但是可以将所有工作委托给实现 Filter 的 Spring Bean。
1 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { |
FilterChainProxy
使用 SecurityFilterChain
确定应对此请求调用哪些 Spring Security 过滤器。
SecurityFilterChain
中的安全过滤器通常是 Bean,但它们是使用 FilterChainProxy
而不是 DelegatingFilterProxy
注册的。
实际上,FilterChainProxy
可用于确定应使用哪个 SecurityFilterChain
。如果您的应用程序可以为不同的模块提供完全独立的配置。
ExceptionTranslationFilter 可以将 AccessDeniedException 和 AuthenticationException 转换为 HTTP 响应。
核心源码:
1 | try { |
认证
数据模型
Spring Security 框架中的认证数据模型如下:
Authentication
- 认证信息实体。principal
- 用户标识。如:用户名、账户名等。通常是UserDetails
的实例(后面详细讲解)。credentials
- 认证凭证。如:密码等。authorities
- 授权信息。如:用户的角色、权限等信息。
SecurityContext
- 安全上下文。包含一个Authentication
对象。SecurityContextHolder
- 安全上下文持有者。用于存储认证信息。
【示例】注册认证信息
1 | SecurityContext context = SecurityContextHolder.createEmptyContext(); |
【示例】访问认证信息
认证基本流程
AbstractAuthenticationProcessingFilter 用作验证用户凭据的基本过滤器。 在对凭证进行身份验证之前,Spring Security 通常使用 AuthenticationEntryPoint 请求凭证。
- (1)当用户提交其凭据时,
AbstractAuthenticationProcessingFilter
从要验证的HttpServletRequest
创建一个Authentication
。创建的身份验证类型取决于AbstractAuthenticationProcessingFilter
的子类。例如,UsernamePasswordAuthenticationFilter
根据在HttpServletRequest
中提交的用户名和密码来创建UsernamePasswordAuthenticationToken
。 - (2)接下来,将身份验证传递到
AuthenticationManager
进行身份验证。 - (3)如果身份验证失败,则认证失败
- 清除
SecurityContextHolder
。 - 调用
RememberMeServices.loginFail
。如果没有配置 remember me,则为空。 - 调用
AuthenticationFailureHandler
。
- 清除
- (4)如果身份验证成功,则认证成功。
- 如果是新的登录,则通知
SessionAuthenticationStrategy
。 - 身份验证是在
SecurityContextHolder
上设置的。之后,SecurityContextPersistenceFilter
将SecurityContext
保存到HttpSession
中。 - 调用
RememberMeServices.loginSuccess
。如果没有配置 remember me,则为空。 ApplicationEventPublisher
发布一个InteractiveAuthenticationSuccessEvent
。
- 如果是新的登录,则通知
用户名/密码认证
读取用户名和密码的方式:
- 表单
- 基本认证
- 数字认证
存储机制
- 内存
- JDBC
- UserDetailsService
- LDAP
表单认证
spring security 支持通过从 html 表单获取登录时提交的用户名、密码。
一旦,登录信息被提交,UsernamePasswordAuthenticationFilter
就会验证用户名和密码。
基本认证
1 | protected void configure(HttpSecurity http) { |
内存认证
InMemoryUserDetailsManager
实现了 UserDetailsService ,提供了基本的用户名、密码认证,其认证数据存储在内存中。
1 |
|
JDBC 认证
JdbcUserDetailsManager 实现了 UserDetailsService ,提供了基本的用户名、密码认证,其认证数据存储在关系型数据库中,通过 JDBC 方式访问。
1 | @Bean |
基本的 scheam:
1 | create table users( |
UserDetailsService
UserDetails
由 UserDetailsService
返回。 DaoAuthenticationProvider
验证 UserDetails
,然后返回身份验证,该身份验证的主体是已配置的 UserDetailsService
返回的 UserDetails
。
DaoAuthenticationProvider
使用 UserDetailsService
检索用户名,密码和其他用于使用用户名和密码进行身份验证的属性。 Spring Security 提供 UserDetailsService
的内存中和 JDBC 实现。
您可以通过将自定义 UserDetailsService
公开为 bean 来定义自定义身份验证。
PasswordEncoder
Spring Security 的 servlet 支持通过与 PasswordEncoder
集成来安全地存储密码。 可以通过公开一个 PasswordEncoder Bean 来定制 Spring Security 使用的 PasswordEncoder 实现。
Remember-Me
Spring Boot 集成
@EnableWebSecurity
和 @Configuration
注解一起使用, 注解 WebSecurityConfigurer
类型的类。
或者利用@EnableWebSecurity
注解继承 WebSecurityConfigurerAdapter
的类,这样就构成了 Spring Security 的配置。
- configure(WebSecurity):通过重载该方法,可配置 Spring Security 的 Filter 链。
- configure(HttpSecurity):通过重载该方法,可配置如何通过拦截器保护请求。