Spring Boot 2.x+Spring Security+JWT构建API时Angular 5 OPTIONS请求403问题
解决Spring Boot + Security + JWT中Angular OPTIONS请求403的问题
嘿,这个问题我太熟了!你遇到的403是因为Spring Security默认拦截了浏览器跨域时自动发送的OPTIONS预检请求——POSTMAN直接发POST不会触发浏览器的预检机制,所以能正常登录,但Angular作为前端框架,跨域请求前会自动发OPTIONS请求确认权限,这一步被Spring Security拦住了。下面是具体的解决步骤:
1. 配置全局CORS规则
先创建一个CORS配置的Bean,允许Angular所在的域名发起跨域请求,同时放行必要的请求方法和头:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.CorsConfigurationSource; import java.util.Arrays; @Configuration public class CorsConfig { @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); // 替换成你的Angular项目地址,比如http://localhost:4200,生产环境别用* config.setAllowedOrigins(Arrays.asList("http://localhost:4200")); // 放行包括OPTIONS在内的所有常用请求方法 config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); // 放行JWT需要的Authorization头,以及Content-Type等 config.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With")); // 允许携带凭证(如果你的请求需要带cookie或认证信息) config.setAllowCredentials(true); // 对所有路径应用这个配置 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } }
2. 在Spring Security中启用CORS并放行OPTIONS请求
修改你的SecurityConfiguration,把CORS配置集成进去,同时明确放行所有OPTIONS请求:
// 导入必要的包 import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.cors.CorsConfigurationSource; import org.springframework.http.HttpMethod; public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private CorsConfigurationSource corsConfigurationSource; @Override protected void configure(HttpSecurity http) throws Exception { http // 启用CORS配置 .cors().configurationSource(corsConfigurationSource).and() // 关闭CSRF(JWT场景下不需要CSRF保护) .csrf().disable() // 配置请求权限规则 .authorizeRequests() // 放行所有OPTIONS预检请求 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行登录接口,允许匿名访问 .antMatchers("/api/v1/login").permitAll() // 其他所有接口需要认证 .anyRequest().authenticated() .and() // 这里添加你的JWT过滤器(比如自定义的JwtAuthenticationFilter) .addFilterBefore(yourJwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class); } // 你的其他配置代码... }
3. 确保JWT过滤器不拦截OPTIONS请求
如果你有自定义的JWT验证过滤器,一定要在过滤器开头判断请求方法,如果是OPTIONS直接放行,不要去解析JWT:
import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.http.HttpMethod; public class JwtAuthenticationFilter extends OncePerRequestFilter { @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { // 遇到OPTIONS请求直接返回200,不用处理JWT if (HttpMethod.OPTIONS.name().equals(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); return; } // 你的JWT解析、认证逻辑... filterChain.doFilter(request, response); } }
4. Angular端的小配置(可选)
如果后端设置了setAllowCredentials(true),Angular的HttpClient请求要加上withCredentials: true,确保凭证能正常传递:
import { HttpClient } from '@angular/common/http'; // 登录请求示例 login(loginData: any) { return this.http.post('http://localhost:8080/api/v1/login', loginData, { withCredentials: true }); }
做完这些配置后,重启Spring Boot服务,再用Angular发起请求,OPTIONS预检应该就能正常通过,不会再返回403了。
内容的提问来源于stack exchange,提问作者Ashutosh
相关产品推荐
相关产品推荐

