上面一篇我们介绍了安全相关的概念以及springSecurity基础原理。了解了什么是认证,授权和鉴权,以及springSecurity是怎么将自己的过滤器链加入到web过滤器链中的。这一篇我们重点介绍springSecurity的重点组件及概念,以及过滤器链的常见过滤器及功能。
1、重点组件
springSecurity主要是帮助我们完成项目中认证和鉴权的过程,首先了解一些常用的概念方便我们后续学习理解。
(1)、SecurityContextHolder
SecurityContextHolder 是一个静态类,用于存储当前线程的 SecurityContext。它使用线程局部变量(ThreadLocal)来实现这一点,这意味着每个线程都有自己独立的 SecurityContext 实例。这种设计使得 SecurityContext 在多线程环境下也能保持线程安全。在Web场景下的使用Spring Security,在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息。
常用方法:
java
1、获取当前线程的 SecurityContext 实例
SecurityContext context = SecurityContextHolder.getContext();
2、设置当前线程的 SecurityContext 实例。
SecurityContext context = new SecurityContextImpl();
SecurityContextHolder.setContext(context);
3、清除当前线程的 SecurityContext 实例
SecurityContextHolder.clearContext();
4、设置存储策略名称。默认策略是 MODE_THREADLOCAL,表示使用线程局部变量。
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
(2)、SecurityContext
SecurityContext是一个接口,用于存储当前用户的认证信息。即保存着当前用户是谁,是否已经通过认证,拥有哪些权限等等。最常用的实现类是 SecurityContextImpl。
常用方法:
java
获取当前用户的认证信息
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
设置当前用户认证信息
SecurityContextHolder.getContext().setAuthentication(authentication);
(3)、Authentication
Authentication 是一个接口,表示用户的认证信息。它包含了一些基本的信息,如用户名、密码、权限等。
常用方法:
java
返回用户的主体信息,通常是 UserDetails 对象
Object principal = authentication.getPrincipal();
返回用户的凭证信息,通常是密码。
Object credentials = authentication.getCredentials();
返回用户的权限列表
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
返回用户的用户名
String name = authentication.getName();
返回用户是否已经认证
boolean isAuthenticated = authentication.isAuthenticated();
设置用户是否已经认证。通常情况下,不应该手动调用此方法。
authentication.setAuthenticated(true);
(4)、UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken 是 Authentication 接口的一个实现类,用于表示基于用户名和密码的认证信息。它通常在用户登录时使用。
常用方法:
java
构造方法,未认证时使用
UsernamePasswordAuthenticationToken unauthenticatedToken = new UsernamePasswordAuthenticationToken(username, password);
构造方法,已认证状态时使用
Collection<GrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
UsernamePasswordAuthenticationToken authenticatedToken = new UsernamePasswordAuthenticationToken(username, password, authorities);
回用户的主体信息,通常是用户名
Object principal = token.getPrincipal();
返回用户的凭证信息,通常是密码。
Object credentials = token.getCredentials();
返回用户的权限列表
Collection<? extends GrantedAuthority> authorities = token.getAuthorities();
返回用户的用户名
String name = token.getName();
返回用户是否已经认证
boolean isAuthenticated = token.isAuthenticated();
以上为最基础的概念
(5)、UsernamePasswordAuthenticationFilter
账号名密码认证过滤器,认证用户登录信息的主入口。
主要完成:
1、拦截 /login 请求,从请求中提取用户名和密码信息。
2、封装用户名和密码信息生成 UsernamePasswordAuthenticationToken。
3、将UsernamePasswordAuthenticationToken 提交给 AuthenticationManager 进行认证。
注意,具体认证方式是由 AuthenticationManager 接口负责的。
(6)、AuthenticationManager
认证管理器,是认证相关的核心接口,也是发起认证的出发点。实际业务中可以根据不同的认证信息进行不同类型的认证,具体的实现是由ProviderManager完成的。
(7)、ProviderManager
认证提供者管理器,是 AuthenticationManager 的一个实现类,用于管理多个 AuthenticationProvider(认证提供者),它会依次调用每个 AuthenticationProvider,只要任何一个认证提供者提供的认证方式通过,认证就结束。
主要功能:
1、管理多个 AuthenticationProvider。
2、依次调用每个 AuthenticationProvider 进行认证。
3、返回第一个成功认证的结果。
(8)、AuthenticationProvider
认证提供者,这是一个接口,具体如何认证,就看如何实现该接口。Spring Security 提供了 DaoAuthenticationProvider 实现该接口,这个类就是使用数据库中数据进行认证。
主要功能:
1、接收 Authentication 对象。
2、执行具体的认证逻辑。
3、返回认证结果。
(9)、DaoAuthenticationProvider
DaoAuthenticationProvider 是 AuthenticationProvider 的一个实现类,用于基于数据库或其他数据源进行认证。它依赖于 UserDetailsService 来加载用户详细信息。
源码中通过retrieveUser方法调用调用了 this.getUserDetailsService().loadUserByUsername(username);实现
主要功能:
1、使用 UserDetailsService 加载用户详细信息。
2、比较用户提供的密码和数据库中的密码。
3、返回认证结果。
配置示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
(10)、UserDetailsService
UserDetailsService 是一个接口,用于加载用户详细信息。它通常用于从数据库或其他数据源中获取用户信息。
主要功能:
1、根据用户名加载用户详细信息。
2、返回 UserDetails 对象。
代码示例:
java
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 从数据库或其他数据源中加载用户信息
if ("user".equals(username)) {
return User.withUsername("user")
.password("{noop}password")
.roles("USER")
.build();
} else if ("admin".equals(username)) {
return User.withUsername("admin")
.password("{noop}admin")
.roles("ADMIN")
.build();
} else {
throw new UsernameNotFoundException("User not found");
}
}
}
(11)、UserDetails
是 Spring Security 中的一个接口,用于表示用户的详细信息。这个接口包含了用户的基本信息,如用户名、密码、权限等。通过实现 UserDetails 接口,你可以自定义用户对象,以便在认证过程中使用。
主要方法:
java
返回用户拥有的权限列表
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
返回用户的密码
String password = userDetails.getPassword();
返回用户的用户名
String username = userDetails.getUsername();
返回账户是否未过期
boolean accountNonExpired = userDetails.isAccountNonExpired();
返回账户是否未锁定
boolean accountNonLocked = userDetails.isAccountNonLocked();
返回凭证(密码)是否未过期
boolean credentialsNonExpired = userDetails.isCredentialsNonExpired();
返回账户是否启用
boolean enabled = userDetails.isEnabled();
(12)、BasicAuthenticationFilter
是一个过滤器,拦截非登录接口,校验token是否合法。合法则放行并根据token解析出用户写到全局变量中。
主要功能:
1、拦截带有 Authorization 头(即token请求头)的请求。
2、从请求头中提取用户名和密码。
3、将用户名和密码封装成 UsernamePasswordAuthenticationToken。
4、将 UsernamePasswordAuthenticationToken 提交给 AuthenticationManager 进行认证。
5、如果认证成功,将认证信息存入 SecurityContext。
配置示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.httpBasic() // 启用 HTTP Basic 认证
.and()
.addFilterAfter(new CustomBasicAuthenticationFilter(), BasicAuthenticationFilter.class);
}
@Bean
public CustomBasicAuthenticationFilter customBasicAuthenticationFilter() {
return new CustomBasicAuthenticationFilter(authenticationManager());
}
}
以上为认证主要流程概念
上面的5-12这几个概念是完成认证流程的主要概念,具体流程如下:
1、UsernamePasswordAuthenticationFilter:处理表单登录请求,提取用户名和密码,创建 UsernamePasswordAuthenticationToken。
2、AuthenticationManager:管理认证过程,委托给 ProviderManager。
3、ProviderManager:管理多个 AuthenticationProvider,依次调用进行认证。
4、AuthenticationProvider:是一个接口,由实现类完成具体的认证逻辑。
5、DaoAuthenticationProvider:是AuthenticationProvider的一个实现类,基于数据库或其他数据源进行认证,依赖于 UserDetailsService。
6、UserDetailsService:加载用户详细信息,返回UserDetails对象。
7、认证成功,生成token返回给客户端
8、客户端携带token再次访问非登录接口,会被BasicAuthenticationFilter拦截验证token
9、验证成功,将认证信息保存到SecurityContext中,继续向下执行。
(13)、AuthenticationEntryPoint
是一个接口,用于处理未认证用户的请求。当用户尝试访问需要认证的资源但未提供有效的认证信息时,Spring Security 会调用 AuthenticationEntryPoint。
主要功能:
1、处理未认证用户的请求。
2、通常用于返回 401 Unauthorized 响应。
实现类代码示例:
java
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized: " + authException.getMessage());
}
}
配置类示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint);
}
}
(14)、AccessDeniedHandler
是一个接口,用于处理已认证但没有足够权限访问某个资源的请求。当用户尝试访问需要特定角色或权限的资源但未满足条件时,Spring Security 会调用 AccessDeniedHandler。
主要功能:
1、处理已认证但没有足够权限的请求。
2、通常用于返回 403 Forbidden 响应。
实现类代码示例:
java
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Forbidden: " + accessDeniedException.getMessage());
}
}
配置类示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAccessDeniedHandler customAccessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(customAccessDeniedHandler);
}
}
(15)、AuthenticationSuccessHandler
是一个接口,用于处理认证成功的请求。当用户成功认证后,Spring Security 会调用 AuthenticationSuccessHandler。
主要功能:
1、处理认证成功的请求。
2、通常用于重定向到成功页面或返回成功响应。
实现类代码示例:
java
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect("/success");
}
}
配置类示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(customAuthenticationSuccessHandler)
.permitAll()
.and()
.logout()
.permitAll();
}
}
(16)、AuthenticationFailureHandler
是一个接口,用于处理认证失败的请求。当用户认证失败时,Spring Security 会调用 AuthenticationFailureHandler。
主要功能:
1、处理认证失败的请求。
2、通常用于重定向到失败页面或返回失败响应。
实现类代码示例:
java
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.sendRedirect("/login?error=true");
}
}
配置类示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureHandler(customAuthenticationFailureHandler)
.permitAll()
.and()
.logout()
.permitAll();
}
}
以上为认证或授权过程中的一些自定义行为处理器
这4个接口中,每一个都是当认证或者授权过程中发生结果后触发,可以是失败的场景也可以是成功后触发。1个成功后执行,3个为失败后促发执行
(17)、FilterSecurityInterceptor
FilterSecurityInterceptor是Spring Security 中负责执行授权检查的核心组件之一。它在请求到达目标资源之前,检查用户是否具有访问该资源的权限。通常情况下,Spring Security 会自动配置 FilterSecurityInterceptor,但我们可以自定义其行为。
springSecurity核心配置类示例:
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.access.vote.UnanimousBased;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.RoleVoter;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomFilterInvocationSecurityMetadataSource securityMetadataSource;
@Autowired
private CustomAccessDecisionManager accessDecisionManager;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.addFilterBefore(securityInterceptor(), FilterSecurityInterceptor.class);
}
@Bean
public FilterSecurityInterceptor securityInterceptor() {
FilterSecurityInterceptor filterSecurityInterceptor = new FilterSecurityInterceptor();
filterSecurityInterceptor.setSecurityMetadataSource(securityMetadataSource);
filterSecurityInterceptor.setAccessDecisionManager(accessDecisionManager);
return filterSecurityInterceptor;
}
}
(18)、FilterInvocationSecurityMetadataSource
FilterInvocationSecurityMetadataSource 负责为每个请求提供所需的权限信息。我们需要实现这个接口,以便根据请求的 URL 和方法返回相应的权限配置。
代码示例:
java
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import java.util.*;
public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
private Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<>();
public CustomFilterInvocationSecurityMetadataSource() {
loadResourceDefine();
}
private void loadResourceDefine() {
// 定义资源与权限的映射关系(根据实际业务查询)
resourceMap.put("/admin/**", Collections.singletonList(new SecurityConfig("ROLE_ADMIN")));
resourceMap.put("/user/**", Collections.singletonList(new SecurityConfig("ROLE_USER")));
}
@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
FilterInvocation fi = (FilterInvocation) object;
String url = fi.getRequestUrl();
for (Map.Entry<String, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {
if (url.matches(entry.getKey())) {
return entry.getValue();
}
}
return null; // 默认允许访问
}
@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
Set<ConfigAttribute> allAttributes = new HashSet<>();
for (Collection<ConfigAttribute> attributes : resourceMap.values()) {
allAttributes.addAll(attributes);
}
return allAttributes;
}
@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}
(19)、AccessDecisionManager
AccessDecisionManager 负责根据用户的角色和权限,决定用户是否有权访问请求的资源。我们需要实现这个接口,并提供具体的决策逻辑。
代码示例:
java
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
import java.util.Iterator;
public class CustomAccessDecisionManager implements AccessDecisionManager {
@Override
public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
if (configAttributes == null || configAttributes.isEmpty()) {
return;
}
for (ConfigAttribute attribute : configAttributes) {
String role = attribute.getAttribute();
for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
if (role.equals(grantedAuthority.getAuthority())) {
return;
}
}
}
throw new AccessDeniedException("Access denied - user does not have the required role");
}
@Override
public boolean supports(ConfigAttribute attribute) {
return true;
}
@Override
public boolean supports(Class<?> clazz) {
return true;
}
}
以上为授权验证过程中的相关概念
当用户请求一个受保护的资源时,FilterSecurityInterceptor 会按以下步骤进行授权校验:
1、获取请求的权限信息:
FilterSecurityInterceptor 调用 FilterInvocationSecurityMetadataSource 的 getAttributes 方法,获取请求所需的所有权限。实际上是从核心配置类HttpSecurity中读取的权限。如下图:
2、获取用户的权限信息:
FilterSecurityInterceptor 从 SecurityContext 中获取当前用户的 Authentication 对象,进而获取用户的权限信息。
3、决策是否授权:
FilterSecurityInterceptor 调用 AccessDecisionManager 的 decide 方法,传入用户的权限信息和请求所需的权限信息。
4、AccessDecisionManager 根据具体的决策逻辑,判断用户是否有权访问请求的资源。
如果用户有权限,请求继续处理;如果没有权限,抛出 AccessDeniedException。
2、过滤器链
过滤器是一种典型的AOP思想,Spring Security 使用一个过滤器链来处理请求,每个过滤器负责不同的安全任务。
(1)、SecurityContextPersistenceFilter
实现类:
org.springframework.security.web.context.SecurityContextPersistenceFilter,这是一个重点的过滤器。
工作过程:
1、初始化和清理 SecurityContext。
2、在请求开始时,从会话中恢复 SecurityContext。
3、在请求结束时,清理 SecurityContext,确保线程安全。
实现:
SecurityContextPersistenceFilter主要是使用SecurityContextRepository在session中保存或更新一个SecurityContext,并将SecurityContext给以后的过滤器使用,来为后续filter建立所需的上下文。 SecurityContext中存储了当前用户的认证以及权限信息。
(2)、WebAsyncManagerIntegrationFilter
实现类:
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
作用:
确保在异步Web请求过程中,SecurityContext能正确传递。
功能:
集成springSecurity与springWeb的异步请求支持。
(3)、HeaderWriterFilter
实现类:
org.springframework.security.web.header.HeaderWriterFilter
作用:
添加安全相关的 HTTP 头部。
功能:
向请求的Header中添加相应的信息,例如,设置 X-Content-Type-Options、X-Frame-Options、X-XSS-Protection 头部来防止各种常见的攻击。
(4)、CsrfFilter
实现类:
org.springframework.security.web.csrf.CsrfFilter
csrf又称跨域请求伪造,SpringSecurity会对所有post请求验证是否包含系统生成的csrf的token信息。一般都会禁用掉。
作用:
防御跨站请求伪造(CSRF)攻击。
功能:
在每个请求中验证 CSRF 令牌,确保请求是由合法用户发出的。
(5)、LogoutFilter
实现类:
org.springframework.security.web.authentication.logout.LogoutFilter
匹配URL为/logout的请求,实现用户退出,清除认证信息。
作用:
处理用户的注销请求。
功能:
执行注销逻辑,清除用户的认证信息和会话。
(6)、UsernamePasswordAuthenticationFilter
实现类:
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
认证操作全靠这个过滤器,默认匹配URL为/login且必须为POST请求。
作用:
处理基于表单的登录认证请求。
功能:
验证用户提交的用户名和密码,如果成功,生成认证信息token返回给客户端。
(7)、DefaultLoginPageGeneratingFilter
实现类:
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
如果没有在配置文件中指定认证页面,则由该过滤器生成一个默认认证页面。如果指定了登录页,该过滤器将不在生效。
作用:
生成默认的登录页面。
功能:
在没有自定义登录页面时,提供一个默认的登录页面。
(8)、DefaultLogoutPageGeneratingFilter
实现类:
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
由此过滤器可以生产一个默认的退出登录页面
作用:
生成默认的注销页面。
功能:
在没有自定义注销页面时,提供一个默认的注销页面。
(9)、BasicAuthenticationFilter
实现类:
org.springframework.security.web.authentication.www.BasicAuthenticationFilter
此过滤器会拦截所有的非登录接口,自动解析HTTP请求中头部Authentication(token),校验token是否合法。合法则放行并根据token解析出用户写到全局变量中。
作用:
处理 HTTP Basic 认证。
功能:
从 HTTP 请求头中提取用户名和密码,并进行认证。
(10)、RequestCacheAwareFilter
实现类:
org.springframework.security.web.savedrequest.RequestCacheAwareFilter
通过HttpSessionRequestCache内部维护了一个RequestCache,用于缓存HttpServletRequest
作用:
处理请求缓存。
功能:
在用户登录后,自动重定向到登录前尝试访问的受保护资源。
(11)、SecurityContextHolderAwareRequestFilter
实现类:
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
针对ServletRequest进行了一次包装,使得request具有更加丰富的API。
作用:
为 HttpServletRequest 提供一些辅助方法。
功能:
使得请求对象在安全上下文中更便于使用,例如提供获取当前用户的方法。
(12)、AnonymousAuthenticationFilter
实现类:
org.springframework.security.web.authentication.AnonymousAuthenticationFilter
当SecurityContextHolder中认证信息为空,则会创建一个匿名用户存入到SecurityContextHolder中。spring security为了兼容未登录的访问,也走了一套认证流程,只不过是一个匿名的身份。
作用:
为未认证的用户提供匿名身份。
功能:
如果用户没有登录,赋予其匿名身份,以便应用程序能够处理匿名用户的请求。
(13)、SessionManagementFilter
实现类:
org.springframework.security.web.session.SessionManagementFilter
SessionManagementFilter用于管理会话安全的重要组件。它通过防止会话固定攻击、管理会话的最大生命周期和限制并发会话数,确保应用程序的安全性。
作用:
处理会话管理相关的功能。
功能:
例如防止会话固定攻击,确保会话在用户认证之后安全。
(14)、ExceptionTranslationFilter
实现类:
org.springframework.security.web.access.ExceptionTranslationFilter
异常转换过滤器位于整个springSecurityFilterChain的后方,用来转换整个链路中出现的异常。
作用:
将认证异常转换为适当的 HTTP 响应。
功能:
处理认证异常(如 AccessDeniedException 和 AuthenticationException),并将其转换为适当的 HTTP 状态码和错误信息。
(15)、FilterSecurityInterceptor
实现类:
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
获取所配置资源访问的授权信息,根据SecurityContextHolder中存储的用户信息来决定其是否有权限。
作用:
执行最终的访问控制决策。
功能:
根据配置的访问决策管理器和投票器,决定请求是否被允许访问目标资源。
学海无涯苦作舟!!!