如何使用Spring Security通过Session属性校验用户登录状态
没问题,我来帮你实现这个Spring Security的集成需求,让除了/api/login之外的所有接口都自动校验登录状态,同时兼容你现有的Session存储用户信息的逻辑。咱们一步一步来:
1. 添加Spring Security依赖
首先得把Spring Security的依赖加到你的项目里,根据你用的构建工具选对应的配置:
Maven(pom.xml)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Gradle(build.gradle)
implementation 'org.springframework.boot:spring-boot-starter-security'
2. 自定义Session认证过滤器
因为你是自己处理登录逻辑并把用户信息存在Session的USER_PROFILE键下,所以需要写一个自定义过滤器,让Spring Security能识别这个Session里的用户信息,认为用户已经完成认证。
创建一个SessionAuthenticationFilter类:
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class SessionAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { HttpSession session = request.getSession(false); // 不自动创建新Session if (session != null) { // 从Session中获取用户信息 Object userProfile = session.getAttribute("USER_PROFILE"); if (userProfile != null && SecurityContextHolder.getContext().getAuthentication() == null) { // 构造Authentication对象,这里可以根据你的UserProfile类调整权限信息 // 如果你的UserProfile有角色/权限,记得把第二个参数换成对应的权限集合 Authentication authentication = new UsernamePasswordAuthenticationToken( userProfile, null, null // 示例:如果有普通用户权限,可换成 AuthorityUtils.createAuthorityList("ROLE_USER") ); // 将认证信息存入SecurityContext,这样Spring Security就会认为用户已登录 SecurityContextHolder.getContext().setAuthentication(authentication); } } filterChain.doFilter(request, response); } }
这里要注意:如果你的USER_PROFILE对象包含用户的角色或权限信息,记得把第三个参数换成对应的权限集合,这样后续可以基于权限做更细粒度的接口控制。
3. 配置Spring Security安全规则
接下来创建Spring Security的配置类,定义哪些接口需要认证,把咱们的自定义过滤器加到过滤器链里:
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.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // 禁用CSRF(如果你的API是给前端调用的,可根据实际业务决定是否开启) .csrf().disable() // 配置请求权限规则 .authorizeHttpRequests(auth -> auth // 放行登录接口,允许匿名访问 .antMatchers("/api/login").permitAll() // 其他所有接口都需要认证 .anyRequest().authenticated() ) // 配置Session管理,沿用你自己的Session创建逻辑 .sessionManagement(session -> session .invalidSessionUrl("/api/login") // Session失效后跳转的地址,可根据需求调整 ) // 把自定义的Session认证过滤器加到官方认证过滤器之前 .addFilterBefore(new SessionAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } }
4. 测试验证
现在你可以启动项目测试:
- 直接调用除
/api/login之外的接口,会返回401未认证; - 先调用
/api/login完成登录(此时Session里会存入USER_PROFILE),再调用其他接口,就能正常访问了; - 当Session失效后,再次调用受保护的接口会回到未认证状态。
如果后续需要基于用户权限控制接口访问,只需要在自定义过滤器里调整Authentication对象的权限集合,Spring Security会自动帮你完成权限校验。
内容的提问来源于stack exchange,提问作者Frank




