Spring Security每次Axios请求均重定向至登录页返回302问题
Axios请求返回302重定向至登录页的解决方案
核心问题分析
- 表单登录默认行为触发重定向:你的Spring Security配置启用了
formLogin(Customizer.withDefaults()),当/api/**接口认证失败时,框架会默认返回302重定向到登录页,这是表单登录的内置逻辑,和你使用的JWT无状态认证不兼容。 - 会话策略不匹配:当前设置
SessionCreationPolicy.ALWAYS,而JWT认证不需要服务器维护会话,应该使用无状态策略。 - 认证失败未自定义响应:没有配置JWT认证失败的专属处理逻辑,导致默认走表单登录的重定向流程。
具体修复步骤
1. 修改Spring Security配置,适配JWT认证
禁用表单登录和HTTP Basic认证,设置无状态会话策略,并自定义认证失败/权限不足的JSON响应:
@Bean SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception{ http.securityContext(context -> context.requireExplicitSave(false)) // 改为无状态会话,适配JWT认证 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .cors(corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource(){ @Override public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Collections.singletonList("http://localhost:5173")); config.setAllowedHeaders(Collections.singletonList("*")); config.setAllowedMethods(Collections.singletonList("*")); config.setAllowCredentials(true); config.setMaxAge(3600L); config.setExposedHeaders(List.of("Authorization")); return config; } })) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(request -> request .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() .requestMatchers(HttpMethod.GET, "/basicAuth/**").permitAll() .requestMatchers(HttpMethod.POST, "/register").permitAll() .requestMatchers(HttpMethod.GET, "/").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .requestMatchers("/api/**").authenticated() ) .addFilterBefore(new JWTTokenValidatorFilter(), BasicAuthenticationFilter.class) .addFilterAfter(new JWTTokenGeneratorFilter(), BasicAuthenticationFilter.class) // 禁用表单登录和HTTP Basic认证 .formLogin(AbstractHttpConfigurer::disable) .httpBasic(AbstractHttpConfigurer::disable) // 自定义认证异常处理,返回401/403 JSON响应 .exceptionHandling(exceptions -> exceptions .authenticationEntryPoint((request, response, authException) -> { response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType(MediaType.APPLICATION_JSON_VALUE); String json = "{\"error\": \"Unauthorized\", \"message\": \"无效或缺失Token\"}"; response.getWriter().write(json); }) .accessDeniedHandler((request, response, accessDeniedException) -> { response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.setContentType(MediaType.APPLICATION_JSON_VALUE); String json = "{\"error\": \"Forbidden\", \"message\": \"权限不足\"}"; response.getWriter().write(json); }) ); return http.build(); }
2. 确保JWTTokenValidatorFilter逻辑正确
检查你的JWTTokenValidatorFilter实现:
- 必须正确提取
Authorization请求头中的Bearer <token>格式内容 - 验证Token的签名、过期时间、Claims合法性
- 验证失败时抛出
AuthenticationException,触发上述配置的401响应
3. 验证Axios请求的Token有效性
- 在Axios请求拦截器中打印
config.headers.Authorization,确认请求头正确携带Bearer <token> - 确认
localStorage中的Token未过期、格式正确
4. 前端处理异常(可选)
如果仍出现302,可在Axios响应拦截器中手动跳转前端登录页:
api.interceptors.response.use( response => response, error => { if (error.response?.status === 302) { window.location.href = '/login'; } return Promise.reject(error); } );
内容的提问来源于stack exchange,提问作者ivans
相关产品推荐
相关产品推荐

