在 Spring Security 中,过滤器链是一系列安全过滤器,它们按照特定顺序处理传入的 HTTP 请求。这些过滤器根据定义的安全规则决定是否允许请求继续、进行身份验证或拒绝访问。
Spring Security 的过滤器链是 Servlet 过滤器机制的一部分,由 FilterChainProxy
实现。链中的每个过滤器执行特定的安全相关功能,例如身份验证、授权或会话管理。
核心概念
1. FilterChainProxy:
• 作为安全过滤器的调度器。
• 根据请求的 URL 将请求委托给一个或多个过滤器链。
2. 安全过滤器:
• 例如 UsernamePasswordAuthenticationFilter
、BasicAuthenticationFilter
、SecurityContextPersistenceFilter
等。
• 每个过滤器在安全流程中执行特定任务。
3. 过滤器链执行:
• 请求依次通过过滤器链,每个过滤器都有机会处理或修改请求/响应。
• 如果任何过滤器拒绝访问,链将停止。
4. 安全配置:
• 使用 Spring Security 的 DSL(领域特定语言)或 XML 配置文件来配置过滤器。
示例场景
假设有以下安全需求:
- •
/public/**
:无需身份验证。 - •
/user/**
:仅允许已认证用户访问。 - •
/admin/**
:仅允许具有ADMIN
角色的用户访问。
安全配置示例:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll() // 无需身份验证
.antMatchers("/user/**").authenticated() // 需要身份验证
.antMatchers("/admin/**").hasRole("ADMIN") // 需要 ADMIN 角色
.anyRequest().denyAll() // 拒绝所有其他请求
.and()
.formLogin(); // 启用基于表单的登录
}
}
过滤器链执行流程:
1. 传入请求:/admin/dashboard
2. 过滤器链:
• SecurityContextPersistenceFilter
:恢复安全上下文。
• UsernamePasswordAuthenticationFilter
:处理登录凭据。
• BasicAuthenticationFilter
:处理 HTTP 基本身份验证(如果适用)。
• ExceptionTranslationFilter
:捕获异常并将其转换为 HTTP 响应。
• FilterSecurityInterceptor
:对 /admin/**
URL 强制执行访问控制。
如果用户已认证并具有 ADMIN
角色,请求将继续到控制器。否则,链将停止,并返回错误响应(例如 403 Forbidden
)。
查看 Spring Boot 中的过滤器链
在 Spring Boot 应用程序中,可以通过启用 Spring Security 的调试日志来查看配置的过滤器链:
logging.level.org.springframework.security=DEBUG
常用的安全过滤器及其职责
以下是 Spring Security 中常用的安全过滤器及其职责和执行顺序:
1. WebAsyncManagerIntegrationFilter
:将 Spring Security 与 Spring MVC 的异步请求处理集成。
2. SecurityContextPersistenceFilter
:管理 SecurityContext
的生命周期(在处理请求前检索并在处理后保存)。
3. HeaderWriterFilter
:向响应中添加安全相关的 HTTP 头(例如 X-Frame-Options
、X-XSS-Protection
)。
4. CsrfFilter
:强制执行防止跨站请求伪造(CSRF)攻击的保护。
5. LogoutFilter
:处理用户注销,清除 SecurityContext
并无效化会话。
6. UsernamePasswordAuthenticationFilter
:通过验证用户名和密码凭据处理基于表单的登录身份验证。
7. ConcurrentSessionFilter
:管理并发会话,如果配置了会话限制,则强制执行。
8. BearerTokenAuthenticationFilter
:处理基于令牌的身份验证,例如 OAuth 2.0 Bearer 令牌。
9. BasicAuthenticationFilter
:处理 HTTP 基本身份验证(验证 Authorization
头中的凭据)。
10. RequestCacheAwareFilter
:在成功认证后恢复原始请求 URL(如果请求被拦截)。
11. SecurityContextHolderAwareRequestFilter
:向请求对象提供 Spring Security 的 SecurityContext
和身份验证详细信息。
12. AnonymousAuthenticationFilter
:如果用户未认证,则提供默认的匿名身份验证对象。
13. SessionManagementFilter
:管理与会话相关的任务,例如会话无效化和跟踪。
14. ExceptionTranslationFilter
:处理访问拒绝异常和身份验证异常,通过重定向或发送适当的响应。
15. FilterSecurityInterceptor
:使用访问控制策略对受保护资源执行最终的访问控制检查。
示例:UsernamePasswordAuthenticationFilter
用户名-密码身份验证流程是 Spring Security 中验证用户凭据(用户名和密码)以允许或拒绝访问受保护资源的过程。该流程由多个组件协同工作,包括过滤器、管理器和提供程序。
以下是该流程的逐步分解:
1. 请求发起:客户端向受保护资源(例如 /login
)发送 HTTP 请求。
2. 拦截请求:UsernamePasswordAuthenticationFilter
拦截请求。
3. 创建 Authentication
对象:过滤器创建一个 Authentication
对象(通常是 UsernamePasswordAuthenticationToken
)。
4. 委托给 AuthenticationManager
:过滤器将身份验证任务委托给 AuthenticationManager
。
5. 身份验证提供程序:AuthenticationManager
将实际身份验证委托给一个或多个 AuthenticationProvider
实例。
6. 验证凭据:DaoAuthenticationProvider
使用 UserDetailsService
从数据源加载用户详细信息,并使用 PasswordEncoder
验证密码。
7. 成功认证:如果认证成功,Authentication
对象被设置到 SecurityContext
中,用户被重定向到原始请求的 URL 或默认的成功 URL。
8. 认证失败:如果认证失败,抛出 AuthenticationException
,用户被重定向到登录页面并显示错误消息。
使用 SecurityFilterChain
配置
以下是如何使用 SecurityFilterChain
实现用户名-密码身份验证流程的示例:
配置类:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers("/public/**").permitAll() // 公共端点
.anyRequest().authenticated() // 保护所有其他端点
.and()
.formLogin() // 启用基于表单的登录
.loginPage("/login") // 自定义登录页面
.permitAll()
.and()
.logout() // 启用注销功能
.permitAll();
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 用于密码哈希的密码编码器
}
@Bean
public AuthenticationManager authenticationManager(
AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
用户详情配置:
@Configuration
public class UserDetailsConfig {
@Bean
public UserDetailsService userDetailsService(PasswordEncoder passwordEncoder) {
UserDetails user = User.builder()
.username("user")
.password(passwordEncoder.encode("password"))
.roles("USER")
.build();
UserDetails admin = User.builder()
.username("admin")
.password(passwordEncoder.encode("admin"))
.roles("ADMIN")
.build();
return new InMemoryUserDetailsManager(user, admin);
}
}
自定义登录页面:
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "login"; // 指向 login.html
}
}
login.html:
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form action="/login" method="post">
<div>
<label for="username">Username:</label>
<input type="text" id="username" name="username">
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" name="password">
</div>
<div>
<button type="submit">Login</button>
</div>
</form>
</body>
</html>
总结
Spring Security 的过滤器链机制为处理 HTTP 请求提供了强大的安全控制能力。通过合理配置过滤器链,可以实现身份验证、授权、会话管理等功能,确保应用程序的安全性。
没有回复内容