You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 16:02:02