Spring Boot中通过URL的JSESSIONID获取Spring Session认证对象
从URL中的JSESSIONID获取Authentication并关联请求
核心思路
Spring Session JDBC会将session数据存储在数据库中,其中Spring Security的Authentication对象会被序列化后存放在session的SPRING_SECURITY_CONTEXT属性里。我们可以通过SessionRepository根据提取到的sessionID查询session,再从中取出Authentication并绑定到当前请求上下文。
修改后的过滤器实现
先修改过滤器,注入Spring Session的SessionRepository来操作session数据:
import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.session.Session; import org.springframework.session.SessionRepository; 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 java.io.IOException; public class JSessionIDFilter extends OncePerRequestFilter { private final SessionRepository<? extends Session> sessionRepository; // 构造器注入SessionRepository public JSessionIDFilter(SessionRepository<? extends Session> sessionRepository) { this.sessionRepository = sessionRepository; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestURI = request.getRequestURI(); int index = requestURI.indexOf(";;jsessionid="); if (index >= 0) { String sessionID = requestURI.substring(index + 12); // 根据sessionID查询session Session session = sessionRepository.findById(sessionID); if (session != null) { // 从session中取出Spring Security上下文 SecurityContext securityContext = session.getAttribute("SPRING_SECURITY_CONTEXT"); if (securityContext != null) { Authentication authentication = securityContext.getAuthentication(); // 验证Authentication有效后绑定到当前请求 if (authentication != null && authentication.isAuthenticated()) { SecurityContextHolder.getContext().setAuthentication(authentication); } } } } // 继续执行后续过滤器链 filterChain.doFilter(request, response); } }
安全配置调整
在Security配置类中,通过依赖注入SessionRepository来实例化过滤器,避免直接new导致无法注入Bean的问题:
import org.springframework.context.annotation.Bean; 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; import org.springframework.session.SessionRepository; @EnableWebSecurity public class SecurityConfig { private final SessionRepository<? extends Session> sessionRepository; public SecurityConfig(SessionRepository<? extends Session> sessionRepository) { this.sessionRepository = sessionRepository; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .addFilterBefore(new JSessionIDFilter(sessionRepository), UsernamePasswordAuthenticationFilter.class) // 保留你的Basic Auth配置 .httpBasic(); return http.build(); } }
注意事项
- 确保Spring Session JDBC的数据库表已正确初始化(框架会自动生成,或可使用官方提供的SQL脚本手动初始化)。
- 如果自定义过Spring Security存储上下文的属性名,需替换代码中的
SPRING_SECURITY_CONTEXT为自定义名称。 - 若sessionID无效或session已过期,
sessionRepository.findById会返回null,此时不会修改当前请求的Authentication,保持原有授权逻辑即可。
内容的提问来源于stack exchange,提问作者masty
相关产品推荐
相关产品推荐

