1. 简介
本系列基于最新Spring Boot 3.x + Spring Security 6.x
版本,由浅入深,从实战到源码分析,详细讲解各种 Spring Security
的使用技巧,适用于初学和进阶使用者。
本系列学习路线:
本系列基于最新Spring Boot 3.x + Spring Security 6.x
版本,由浅入深,从实战到源码分析,详细讲解各种 Spring Security
的使用技巧,适用于初学和进阶使用者。
本系列学习路线:
在用户认证过程中,常见的方式是通过用户名和密码进行验证。认证服务首先根据提供的用户名从存储中检索用户信息,随后验证输入的密码是否与存储中的密码匹配。Spring Security 提供多种灵活的用户名和密码存储机制供选择,如下:
内存:将用户信息直接配置在内存中,适用于小型应用或者测试环境。这种方式的配置相对简单,但不适合生产环境。
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER")
.and()
.withUser("admin").password("admin").roles("USER", "ADMIN");
}
Spring Security
通过过滤器来支持Servlet
,即在请求到达Servlet之
前,通过过滤器进行认证和授权校验。如果用户合法且具备权限,则允许请求通过;反之,将会导致跳转到登录页或拒绝访问。因此,本文重点介绍Spring Security
中与过滤器相关的知识。
类比JAVA Web
中的过滤器,Spring Security
中的过滤器进行了各种代理和增强,可以简单理解Security
中的过滤器结构如下所示:
本篇文章主要介绍 Spring Security
中默认的 15
个过滤器实现原理和作用。
Spring
扩展了 Servlet
中原生的过滤器,给予其各种Spring
能力。
GenericFilterBean 在 Spring 中提供了一种抽象的方式来实现过滤器,它继承了jakarta.servlet.Filter 接口,并提供了其他一些便于在 Spring 中使用过滤器的功能。例如,GenericFilterBean 可以通过 BeanNameAware 接口获取 bean 的名称,通过 EnvironmentAware 接口获取 Spring 上下文的环境信息,通过 ServletContextAware 接口获取 Web 应用程序的 ServletContext 对象,以及通过 InitializingBean 和 DisposableBean 接口在 bean 初始化和销毁时执行自定义的逻辑。
本篇文章主要学习 Spring Security
中认证相关组件,为下篇分析用户名密码认证执行流程 打个基础。
Spring Security
提供了多种认证方式登录系统:
OpenID Connect
和OAuth 2.0
登录SAML 2.0
登录JAAS
认证本篇文章主要学习Spring Security
中用户名密码认证的执行流程。
在前面我们已经提到了Spring Security
是基于过滤器实现的,并介绍了过滤器及相关的认证组件。现在,我们将深入源码,详细了解用户名密码认证的整个流程。
在前面我们已经提到了Spring Boot
自动配置了添加了默认的认证规则:
@Bean
@Order(2147483642)
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
// 配置所有的Http请求必须认证
((AuthorizeHttpRequestsConfigurer.AuthorizedUrl)http.authorizeHttpRequests().anyRequest()).authenticated();
// 开启表单登录
http.formLogin();
// 开启Basic认证
http.httpBasic();
return (SecurityFilterChain)http.build();
}
Spring Security
提供了默认的认证规则,同时也支持各种自定义配置。本文档的重点在于深入研究 Spring Security
中表单登录的相关自定义配置。
对于未认证的请求,Spring Security 会将其重定向到默认的登录页面。同时,也支持自定义登录页面。首先,可以创建一个简单的登录页 login.html
,并将其放置在 resources\static
目录下。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username"/><br>
密码: <input type="password" name="password"/><br>
<input type="submit" value="登录"/>
</form>
</body>
</html>