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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:32:30