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

Vue.js调用带JWT的Spring Boot接口遇CORS拦截问题求助

问题解决:Vue调用Spring Boot带JWT接口的CORS错误

问题现象

使用Vue.js前端调用Spring Boot后端接口,携带JWT令牌请求时触发CORS错误,错误信息如下:

"Access to fetch at 'http://127.0.0.1:8081/api/v1/posts/userPosts' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled."
"PostService.js:12 GET http://127.0.0.1:8081/api/v1/posts/userPosts net::ERR_FAILED"

已尝试添加@CrossOrigin注解、全局CorsConfig配置类,但均无效;仅当Spring Security放开所有/api/v1/**接口无需认证时请求正常,限制认证后就触发CORS错误。

核心原因

带Authorization头的请求属于非简单请求,浏览器会先发OPTIONS预检请求,这个请求不会携带JWT令牌,被Spring Security的认证拦截,导致CORS配置的响应头无法返回,进而触发浏览器的CORS错误。

解决方案

1. 让Spring Security启用CORS配置

在SecurityConfig的securityFilterChain方法中添加.cors(withDefaults()),让Spring Security应用你已配置的全局CORS规则:

package com.blog.security.config;

import com.blog.user.User;
import lombok.RequiredArgsConstructor;
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final JwtAuthenticationFilter jwtAuthFilter;
    private final AuthenticationProvider authenticationProvider;

    @Bean
    public SecurityFilterChain securityFilterChain(@NotNull HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf()
                .disable()
                .cors(withDefaults()) // 启用CORS配置
                .authorizeHttpRequests()
                .requestMatchers("/api/v1/posts","/api/v1/auth/register","/api/v1/auth/login")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
        
        return httpSecurity.build();
    }
}

2. 放行OPTIONS预检请求

在SecurityConfig中添加对OPTIONS请求的全局放行,确保预检请求不被认证拦截:

// 在authorizeHttpRequests中添加:
.requestMatchers(HttpMethod.OPTIONS).permitAll()

完整修改后的securityFilterChain:

@Bean
public SecurityFilterChain securityFilterChain(@NotNull HttpSecurity httpSecurity) throws Exception {
    httpSecurity
            .csrf()
            .disable()
            .cors(withDefaults())
            .authorizeHttpRequests()
            .requestMatchers(HttpMethod.OPTIONS).permitAll() // 放行OPTIONS请求
            .requestMatchers("/api/v1/posts","/api/v1/auth/register","/api/v1/auth/login")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);
    
    return httpSecurity.build();
}

3. 确保JWT过滤器不拦截OPTIONS请求

如果自定义了JwtAuthenticationFilter,在doFilterInternal方法中添加判断,直接放行OPTIONS请求:

@Override
protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
    // 放行OPTIONS预检请求
    if (HttpMethod.OPTIONS.name().equals(request.getMethod())) {
        response.setStatus(HttpServletResponse.SC_OK);
        return;
    }
    // 原有JWT校验逻辑
    String authHeader = request.getHeader("Authorization");
    String jwt = null;
    String username = null;
    // ... 后续逻辑
}

额外验证

  • 确认CorsConfig中的allowedOrigins是前端实际的地址http://localhost:8080,与浏览器控制台显示的origin一致
  • 前端请求的Content-Type为application/json,属于非简单请求,必然触发预检,需确保上述配置生效

内容的提问来源于stack exchange,提问作者Ondra David

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 08:37:23