对于最新的稳定版本,请使用 Spring Security 6.5.3spring-doc.cadn.net.cn

持久身份验证

用户首次请求受保护的资源时,系统会提示他们输入凭据。 提示输入凭据的最常见方法之一是将用户重定向到登录页面。 请求受保护资源的未经身份验证的用户的汇总 HTTP 交换可能如下所示:spring-doc.cadn.net.cn

示例 1.未经身份验证的用户请求受保护的资源
GET / HTTP/1.1
Host: example.com
Cookie: SESSION=91470ce0-3f3c-455b-b7ad-079b02290f7b
HTTP/1.1 302 Found
Location: /login

用户提交其用户名和密码。spring-doc.cadn.net.cn

提交的用户名和密码
POST /login HTTP/1.1
Host: example.com
Cookie: SESSION=91470ce0-3f3c-455b-b7ad-079b02290f7b

username=user&password=password&_csrf=35942e65-a172-4cd4-a1d4-d16a51147b3e

对用户进行身份验证后,用户将与新的会话 ID 相关联,以防止会话固定攻击spring-doc.cadn.net.cn

经过身份验证的用户与新会话相关联
HTTP/1.1 302 Found
Location: /
Set-Cookie: SESSION=4c66e474-3f5a-43ed-8e48-cc1d8cb1d1c8; Path=/; HttpOnly; SameSite=Lax

后续请求包括会话 cookie,用于在会话的剩余时间内对用户进行身份验证。spring-doc.cadn.net.cn

作为凭据提供的经过身份验证的会话
GET / HTTP/1.1
Host: example.com
Cookie: SESSION=4c66e474-3f5a-43ed-8e48-cc1d8cb1d1c8

SecurityContext存储库

在 Spring Security 中,用户与未来请求的关联是使用SecurityContextRepository.spring-doc.cadn.net.cn

HttpSecurityContext存储库

默认实现SecurityContextRepositoryHttpSessionSecurityContextRepository它关联了SecurityContextHttpSession. 用户可以将HttpSessionSecurityContextRepository使用另一个实现SecurityContextRepository如果他们希望以其他方式将用户与后续请求相关联,或者根本不关联。spring-doc.cadn.net.cn

NullSecurityContextRepository

如果不希望将SecurityContext设置为HttpSession(即使用 OAuth 进行身份验证时)NullSecurityContextRepositorySecurityContextRepository这没有任何作用。spring-doc.cadn.net.cn

请求属性安全上下文存储库

RequestAttributeSecurityContextRepository保存SecurityContext作为请求属性,以确保SecurityContext可用于跨调度类型发生的单个请求,这些请求可能会清除SecurityContext.spring-doc.cadn.net.cn

例如,假设客户端发出请求,经过身份验证,然后发生错误。 根据 servlet 容器实现,该错误意味着任何SecurityContext已建立的已清除,然后进行错误分派。 进行错误分派时,没有SecurityContext既定。 这意味着错误页面不能使用SecurityContext用于授权或显示当前用户,除非SecurityContext以某种方式持续存在。spring-doc.cadn.net.cn

使用 RequestAttributeSecurityContextRepository
public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		// ...
		.securityContext((securityContext) -> securityContext
			.securityContextRepository(new RequestAttributeSecurityContextRepository())
		);
	return http.build();
}
<http security-context-repository-ref="contextRepository">
	<!-- ... -->
</http>
<b:bean name="contextRepository"
	class="org.springframework.security.web.context.RequestAttributeSecurityContextRepository" />

SecurityContextPersistenceFilter

SecurityContextPersistenceFilter负责持久化SecurityContext在请求之间使用SecurityContextRepository.spring-doc.cadn.net.cn

securityContextpersistence过滤器

1号在运行应用程序的其余部分之前,SecurityContextPersistenceFilter加载SecurityContextSecurityContextRepository并将其设置为SecurityContextHolder.spring-doc.cadn.net.cn

2号接下来,运行应用程序。spring-doc.cadn.net.cn

3号最后,如果SecurityContext已更改,我们保存SecurityContext使用SecurityContextPersistenceRepository. 这意味着当使用SecurityContextPersistenceFilter,只需将SecurityContextHolder将确保SecurityContext使用SecurityContextRepository.spring-doc.cadn.net.cn

在某些情况下,响应会提交并写入客户端,然后再提交SecurityContextPersistenceFilter方法完成。 例如,如果将重定向发送到客户端,则响应会立即写回客户端。 这意味着建立HttpSession在步骤 3 中是不可能的,因为会话 ID 无法包含在已编写的响应中。 另一种可能发生的情况是,如果客户端成功进行身份验证,则响应会在SecurityContextPersistenceFilter完成,客户端在SecurityContextPersistenceFilter完成第二个请求中可能存在错误的身份验证。spring-doc.cadn.net.cn

为避免这些问题,请SecurityContextPersistenceFilterHttpServletRequestHttpServletResponse以检测SecurityContext已更改,如果是,请保存SecurityContext就在提交响应之前。spring-doc.cadn.net.cn

SecurityContextHolder过滤器

SecurityContextHolderFilter负责加载SecurityContext在请求之间使用SecurityContextRepository.spring-doc.cadn.net.cn

securitycontextholderfilter

1号在运行应用程序的其余部分之前,SecurityContextHolderFilter加载SecurityContextSecurityContextRepository并将其设置为SecurityContextHolder.spring-doc.cadn.net.cn

2号接下来,运行应用程序。spring-doc.cadn.net.cn

SecurityContextPersisteneFilter,SecurityContextHolderFilter仅加载SecurityContext它不会保存SecurityContext. 这意味着当使用SecurityContextHolderFilter,则要求SecurityContext被显式保存。spring-doc.cadn.net.cn

显式保存 SecurityContext
public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		// ...
		.securityContext((securityContext) -> securityContext
			.requireExplicitSave(true)
		);
	return http.build();
}
<http security-context-explicit-save="true">
	<!-- ... -->
</http>