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

在Thymeleaf与Spring中如何在请求头中传递JWT Token?

问题分析与解决方案

你当前的做法存在核心问题:在登录控制器中给响应设置Authorization头,浏览器不会自动将这个响应头的值携带到后续的请求中。再加上你配置了SessionCreationPolicy.STATELESS禁用会话,没有持久化的状态存储,所以必须换一种方式让前端请求自动带上JWT Token。

具体解决步骤

1. 调整登录控制器,将Token传递到前端页面

放弃给响应头设置Token,改为把Token放入模型中,传递到登录成功跳转的页面:

@PostMapping("/login")
public ModelAndView processLogin(Authentication authentication) {
    // 替换为你实际的JWT生成逻辑,从authentication中提取用户信息生成Token
    String jwtToken = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZXkiLCJpYXQiOjE2ODMxNzkxODMsImV4cCI6MTY4MzI2NTU4M30.3-_7VrfDg91TUKvHh18JIclt-NTmcx9UnZnsNMoCKyA";
    
    // 跳转到dashboard页面,将Token传入模型
    ModelAndView mv = new ModelAndView("dashboard");
    mv.addObject("jwtToken", jwtToken);
    return mv;
}

2. 在Thymeleaf页面中存储Token并配置全局请求拦截

在登录成功后的页面(如dashboard.html)添加JS代码,将Token存入本地存储,并让所有AJAX请求自动携带Authorization头:

<script th:inline="javascript">
    // 从Thymeleaf模型中获取Token并存储到localStorage
    const token = [[${jwtToken}]];
    if (token) {
        localStorage.setItem("jwtToken", token);
    }

    // 配置jQuery AJAX全局拦截器(使用jQuery时)
    $(document).ready(function() {
        $.ajaxSetup({
            beforeSend: function(xhr) {
                const storedToken = localStorage.getItem("jwtToken");
                if (storedToken) {
                    xhr.setRequestHeader("Authorization", "Bearer " + storedToken);
                }
            }
        });
    });

    // 原生Fetch请求封装(不使用jQuery时)
    function fetchWithToken(url, options = {}) {
        const storedToken = localStorage.getItem("jwtToken");
        options.headers = {
            ...options.headers,
            "Authorization": storedToken ? "Bearer " + storedToken : ""
        };
        return fetch(url, options);
    }
</script>

3. 修复Spring Security配置冲突

你当前同时启用了formLogin和SessionCreationPolicy.STATELESS,这两者存在冲突——formLogin默认依赖会话维持登录状态,而STATELESS会禁用会话。建议调整配置:

@Bean
public SecurityFilterChain config(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .authorizeHttpRequests(auth -> auth
                    .requestMatchers("/css/**","/scss/**","/vendor/**","/img/**","/js/**").permitAll()
                    .requestMatchers("/auth","/register", "/login").permitAll()
                    .anyRequest().authenticated()
            )
            .sessionManagement(session -> session
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .authenticationProvider(authenticationProvider())
            // 移除formLogin,改用自定义登录流程(避免与无状态会话冲突)
            .logout(logout -> logout
                    .logoutSuccessUrl("/logout")
                    .invalidateHttpSession(true)
                    .deleteCookies("JSESSIONID")
                    .permitAll()
            )
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
    return http.build();
}

4. 处理非AJAX的页面跳转请求

如果是Thymeleaf的a标签整页跳转请求,浏览器不会自动携带Authorization头,可改用Cookie存储Token的方式:

  • 在登录控制器中设置Cookie:
@PostMapping("/login")
public ModelAndView processLogin(HttpServletResponse response) {
    String jwtToken = "你的Token";
    Cookie cookie = new Cookie("jwtToken", jwtToken);
    cookie.setHttpOnly(true); // 防范XSS攻击
    cookie.setSecure(true); // 生产环境开启,仅HTTPS下传递
    cookie.setPath("/");
    cookie.setMaxAge(86400); // 有效期1天
    response.addCookie(cookie);
    
    ModelAndView mv = new ModelAndView("dashboard");
    return mv;
}
  • 修改JwtAuthFilter从Cookie中获取Token:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    String jwtToken = null;
    Cookie[] cookies = request.getCookies();
    if (cookies != null) {
        for (Cookie cookie : cookies) {
            if ("jwtToken".equals(cookie.getName())) {
                jwtToken = cookie.getValue();
                break;
            }
        }
    }
    
    // 后续Token验证逻辑...
    filterChain.doFilter(request, response);
}

内容的提问来源于stack exchange,提问作者maudderung

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:47:03