本地开发React/Springboot无法传递fusionauth的app.at Cookie至后端
核心问题分析
- FusionAuth生成的
app.atCookie默认开启httpOnly属性,前端JS无法直接读取,因此无法手动将Token放入请求头的Authorization字段。 - Spring Security的
BearerTokenAuthenticationFilter默认仅从请求头Authorization: Bearer <token>或请求参数中提取Token,不会自动读取Cookie中的app.at。 - 前端Axios配置中错误设置了
Access-Control-Allow-Origin: *,当withCredentials: true时,该值不能为通配符,会导致Cookie无法被携带。
分步解决方案
1. 修正前端Axios配置
删除前端Axios中无效的Access-Control-Allow-Origin响应头(该头由后端返回,前端设置无意义),确保withCredentials: true正确生效:
const api = axios.create({ withCredentials: true, baseURL: 'http://localhost:8080/api', headers: { 'Content-Type': 'application/json', }, });
2. 让SpringBoot从Cookie中提取app.at Token
两种方案选其一即可:
方案一:自定义过滤器将Cookie转成Authorization头
编写过滤器读取app.at Cookie的值,注入到请求头的Authorization字段中,让BearerTokenAuthenticationFilter能识别:
@Component public class FusionAuthCookieToHeaderFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("app.at".equals(cookie.getName())) { String token = cookie.getValue(); // 包装请求,添加Authorization头 request = new HttpServletRequestWrapper(request) { @Override public String getHeader(String name) { if ("Authorization".equals(name)) { return "Bearer " + token; } return super.getHeader(name); } @Override public Enumeration<String> getHeaders(String name) { if ("Authorization".equals(name)) { return Collections.enumeration(Collections.singletonList("Bearer " + token)); } return super.getHeaders(name); } }; break; } } } filterChain.doFilter(request, response); } }
然后在Security配置中,将该过滤器添加到BearerTokenAuthenticationFilter之前:
@Bean public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http, FusionAuthCookieToHeaderFilter cookieFilter) throws Exception { http.cors(corsConfig -> corsConfig.configurationSource(corsConfigurationSource())) // 自定义过滤器放在BearerToken过滤器之前 .addFilterBefore(cookieFilter, BearerTokenAuthenticationFilter.class) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))) // 其他安全配置... .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()); return http.build(); }
方案二:自定义BearerTokenResolver直接从Cookie取Token
通过配置Spring Security的BearerTokenResolver,让它优先从Cookie中读取app.at:
@Bean public SecurityFilterChain resourceServerSecurityFilterChain(HttpSecurity http) throws Exception { http.cors(corsConfig -> corsConfig.configurationSource(corsConfigurationSource())) .oauth2ResourceServer(oauth2 -> oauth2 .bearerTokenResolver(request -> { // 先从Cookie读取app.at Cookie[] cookies = request.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { if ("app.at".equals(cookie.getName())) { return cookie.getValue(); } } } // fallback到默认的解析逻辑(请求头/参数) return new DefaultBearerTokenResolver().resolve(request); }) .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())) ) .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()); return http.build(); }
3. 检查FusionAuth的Cookie配置
登录FusionAdmin后台,进入对应应用的Security配置页,调整Cookie设置:
- Domain:本地开发可留空或设置为
localhost - Path:设为
/ - SameSite:设为
Lax(本地http环境),若为https可设为None(需开启Secure) - Secure:本地http环境关闭,https环境开启
确保这些配置正确,否则浏览器可能不会在跨域请求中携带app.at Cookie。
4. 验证请求流程
- 登录FusionAuth后,打开浏览器开发者工具的
Application面板,确认app.atCookie存在且属性符合上述配置。 - 前端发起请求时,查看
Network面板的请求头,确认Cookie: app.at=<token>已被携带。 - 后端调试时,确认
BearerTokenAuthenticationFilter已能获取到Token。
内容的提问来源于stack exchange,提问作者flareback
相关产品推荐
相关产品推荐

