1. 概念
Spring Security:Spring 提供的安全框架,用于保护应用程序免受未授权访问,提供认证、授权、CSRF 防护等功能。
核心功能:
认证(Authentication):确认用户身份(登录过程)。
授权(Authorization / Access Control):控制用户访问资源的权限。
安全上下文(SecurityContext):存储当前用户信息的容器。
过滤器链(Filter Chain):拦截请求,按顺序执行安全逻辑。
2. 核心组件
组件 作用 UserDetailsService 用户信息服务,用于根据用户名查询用户信息(用户名、密码、权限) UserDetails 用户信息接口(用户名、密码、权限、状态) GrantedAuthority 用户权限/角色接口,用于授权判断 PasswordEncoder 密码加密器,如 BCryptPasswordEncoder
AuthenticationManager 认证管理器,负责执行认证逻辑 SecurityContextHolder 存储认证信息的上下文,当前线程可访问 HttpSecurity 配置 HTTP 请求安全策略(认证/授权、表单登录、CSRF 等) FilterChainProxy 核心过滤器链,所有请求经过一系列安全过滤器处理
3. 常见配置方式(Spring Boot)
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {// 用户信息服务@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();manager.createUser(User.withUsername("zhangsan").password("123").authorities("p1").build());manager.createUser(User.withUsername("lisi").password("456").authorities("p2").build());return manager;}// 密码编码器@Beanpublic PasswordEncoder passwordEncoder() {return NoOpPasswordEncoder.getInstance();}// HTTP 安全配置@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/r/r1").hasAuthority("p1").antMatchers("/r/r2").hasAuthority("p2").antMatchers("/r/**").authenticated().anyRequest().permitAll().and().formLogin().successForwardUrl("/login-success"); // 登录成功后转发} }
4.认证与授权流程
4.1 结构总览
Spring Security所解决的问题就是安全访问控制,而安全访问控制功能其实就是对所有进入系统的请求进行拦截, 校验每个请求是否能够访问它所期望的资源。根据前边知识的学习,可以通过Filter或AOP等技术来实现,Spring Security对Web资源的保护是靠Filter实现的,所以从这个Filter来入手,逐步深入Spring Security原理。当初始化Spring Security时,会创建一个名为 SpringSecurityFilterChain 的Servlet过滤器,类型为 org.springframework.security.web.FilterChainProxy,它实现了javax.servlet.Filter,因此外部的请求会经过此类,下图是Spring Security过虑器链结构图:
FilterChainProxy是一个代理,真正起作用的是FilterChainProxy中SecurityFilterChain所包含的各个Filter,同时 这些Filter作为Bean被Spring管理,它们是Spring Security核心,各有各的职责,但他们并不直接处理用户的认 证,也不直接处理用户的授权,而是把它们交给了认证管理器(AuthenticationManager)和决策管理器(AccessDecisionManager)进行处理,下图是FilterChainProxy相关类的UML图示。
spring Security功能的实现主要是由一系列过滤器链相互配合完成。
下面介绍过滤器链中主要的几个过滤器及其作用:(1)SecurityContextPersistenceFilter:这个Filter是整个拦截过程的入口和出口(也就是第一个和最后一个拦截 器),会在请求开始时从配置好的 SecurityContextRepository 中获取 SecurityContext,然后把它设置给 SecurityContextHolder。在请求完成后将 SecurityContextHolder 持有的 SecurityContext 再保存到配置好的 SecurityContextRepository,同时清除 securityContextHolder 所持有的 SecurityContext;(2)UsernamePasswordAuthenticationFilter用于处理来自表单提交的认证。该表单必须提供对应的用户名和密码,其内部还有登录成功或失败后进行处理的AuthenticationSuccessHandler和 AuthenticationFailureHandler,这些都可以根据需求做相关改变;(3)FilterSecurityInterceptor是用于保护web资源的,使用AccessDecisionManager对当前用户进行授权访问,前面已经详细介绍过了;(4)ExceptionTranslationFilter能够捕获来自 FilterChain 所有的异常,并进行处理。但是它只会处理两类异常:AuthenticationException 和 AccessDeniedException,其它的异常它会继续抛出。4.2 认证(Authentication)流程
用户提交登录请求(POST
/login
或表单提交)。UsernamePasswordAuthenticationFilter 拦截请求。
AuthenticationManager 调用 ProviderManager。
AuthenticationProvider 使用 UserDetailsService 加载用户信息。
PasswordEncoder 验证密码是否匹配。
如果验证成功:
创建 Authentication 对象(包含用户名、权限)。
保存到 SecurityContextHolder 中。
登录成功,执行 successHandler 或 successForwardUrl。
图示:
用户登录请求 → UsernamePasswordAuthenticationFilter → AuthenticationManager → AuthenticationProvider → UserDetailsService → 密码验证 → SecurityContextHolder 保存用户信息 → 登录成功处理
图解以及解析
让我们仔细分析认证过程:
4.3 授权(Authorization)流程
请求到达 Controller 前,由 FilterSecurityInterceptor 处理。
获取当前用户的 Authentication(从 SecurityContextHolder)。
对比请求资源的 权限配置(如
.antMatchers("/r/r1").hasAuthority("p1")
)。判断用户是否拥有访问权限:
有权限 → 放行,访问 Controller 方法。
无权限 → 拦截,返回 403 或跳转到 Access Denied 页面。
Controller 执行完毕,视图渲染返回响应。
图示:
HTTP 请求 → FilterSecurityInterceptor → SecurityContextHolder 获取 Authentication → 对比权限 → 放行/拒绝 → Controller 方法执行 → 返回响应
图解以及解析
分析授权流程:
5. 权限控制方式
基于 URL 的权限控制(HttpSecurity 配置)
.antMatchers("/r/r1").hasAuthority("p1")
基于方法的权限控制(Spring 方法级安全)
@PreAuthorize("hasAuthority('p1')")
@Secured("ROLE_ADMIN")
6. 常见注意事项
UserDetailsService
只负责查询用户信息,不负责认证逻辑。
PasswordEncoder
必须与存储密码一致,否则密码匹配失败。
successForwardUrl
→ 服务器内部转发,需要自己提供对应 Controller 或页面。
authenticated()
与hasAuthority()
的区别:
authenticated()
→ 已登录即可访问
hasAuthority("p1")
→ 必须具备指定权限才能访问Spring Boot 引入
spring-boot-starter-security
→ 默认启用 Security,无需@EnableWebSecurity
(除非想自定义配置)。
✅ 总结流程:
认证:用户身份验证 → 创建 Authentication → 保存到 SecurityContextHolder
授权:访问请求 → 检查 Authentication 权限 → 放行/拒绝