Angular + Spring Boot 架构下JWT刷新令牌Cookie未在浏览器中设置的问题求助
各位大佬好,我最近在做Angular+Spring Boot的认证流程,碰到了一个卡了我好久的问题:
我的Angular前端跑在http://localhost:4200,Spring Boot后端在http://localhost:8080。登录成功后,后端会通过Set-Cookie头返回一个HttpOnly的刷新令牌,我在浏览器的网络请求响应里明明能看到这个头,但浏览器就是不把这个Cookie存起来——DevTools的Application→Storage→Cookies里完全找不到它,后续调用/auth/refresh接口的时候,这个Cookie也不会自动带上,导致刷新令牌失效。
下面是我的相关代码,麻烦大家帮忙看看哪里出问题了:
后端Spring Boot:Cookie设置代码
我是手动拼接Set-Cookie头的:
private TokenResponse generateTokenResponse(String usernameOrEmail, HttpServletResponse response) { UserEntity user = userService.findByUserNameOrEmail(usernameOrEmail); Set<String> roles = userService.getUserRoles(user); String token = jwtTokenProvider.generateToken(user.getUserName(), roles); String refreshToken = jwtTokenProvider.generateRefreshToken(user.getUserName()); // 手动构建HttpOnly刷新令牌的Cookie头 String cookieValue = "refresh_token=" + refreshToken + "; HttpOnly; Path=/auth/refresh; Max-Age=" + (7 * 24 * 60 * 60) + "; SameSite=Lax"; response.addHeader("Set-Cookie", cookieValue); return new TokenResponse(token, jwtTokenProvider.getJwtExpirationInMs() / 1000, roles); }
后端Spring Boot:CORS配置
我已经开了allowCredentials,也指定了允许的Origin:
@Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowCredentials(true); configuration.setAllowedOrigins(List.of("http://localhost:4200")); configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); configuration.setAllowedHeaders(List.of("*")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
前端Angular:HTTP请求代码
我在调用刷新接口的时候已经设置了withCredentials: true:
this.http.post('/auth/refresh', body, { withCredentials: true }).subscribe();
我自己排查的几个方向,但还没解决:
- 手动拼接Cookie的格式问题:会不会是我手动写的Cookie字符串有格式错误?比如分号、空格的位置不对?是不是应该用Spring自带的
Cookie类来构建,而不是自己拼字符串?比如:
Cookie refreshCookie = new Cookie("refresh_token", refreshToken); refreshCookie.setHttpOnly(true); refreshCookie.setPath("/auth/refresh"); refreshCookie.setMaxAge(7 * 24 * 60 * 60); refreshCookie.setSameSite("Lax"); response.addCookie(refreshCookie);
这样会不会更规范,避免手动拼接的格式错误?
登录请求的
withCredentials设置:我刚才贴的是刷新接口的请求代码,但**登录请求(也就是触发Set-Cookie的那个请求)**里,我有没有加withCredentials: true?哦对,我好像只在刷新请求里加了,登录请求没加!是不是浏览器会因为登录请求没带withCredentials,就拒绝接受Set-Cookie头?这会不会是核心问题?Cookie的Path设置:我把Path设为
/auth/refresh,是不是只有当请求这个路径时才会带上Cookie?但我的刷新请求就是这个路径,理论上应该没问题?或者是不是应该把Path设为/,覆盖所有路径?SameSite和Secure属性:我本地用的是HTTP,所以没加Secure属性,SameSite设的是Lax,这个在HTTP环境下是允许的吧?如果是HTTPS的话才需要加Secure?
麻烦各位大佬帮我分析分析,到底哪里出问题了,谢谢大家!🙏
内容来源于stack exchange

