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

本地开发时Next.js与SpringBoot的CORS配置异常排查

问题描述

我正尝试从Next.js前端(localhost:3000)向Java SpringBoot服务端(localhost:5555)发起本地网络请求,但SpringBoot服务端持续出现以下错误:

[nio-3000-exec-2] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for OPTIONS "/error", parameters={}

[nio-3000-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 403

我的WebMvcConfigurer配置如下:

package com.codaholic.shop.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:5555")
                .exposedHeaders("*")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

Next.js前端控制台的错误日志如下:

Access to fetch at 'http://localhost:3000/api/v1/article' from origin 'http://localhost:5555' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

/api/v1/article接口的代码如下:

@GetMapping("")
public ResponseEntity<List<Article>> getArticleByUser()
        throws ResourceNotFoundException {
    CustomUserDetails userDetails = (CustomUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UUID userId = userDetails.getUserId();
    List<Article> articles = articleService.getArticlesByUserId(userId);

    return ResponseEntity.ok().body(articles);
};

不过发起登录接口的API请求时不会遇到相同错误,我不确定缺少哪些配置或该如何调试。当前使用的是SpringBoot 3.1.3版本。

补充说明1

另外补充一点,我已通过以下配置禁用了csrf:
SecurityConfiguration.java

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity
public class SecurityConfiguration {

    private final JwtAuthenticationFilter jwtAuthFilter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf((csrf) -> csrf.disable()
                )
            .authorizeHttpRequests((authorize)-> authorize
                    .dispatcherTypeMatchers(DispatcherType.ERROR).permitAll()
                    .requestMatchers(
                        "/api/v1/auth/**",
                        "/swagger-ui/**",
                        "/swagger",
                        "/swagger-ui.html"
                    )
                    .permitAll()
                    .anyRequest()
                    .authenticated()

            )
            .sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

解决方案

1. 修正CORS配置的源地址

你的WebMvcConfiguration里allowedOrigins写反了——前端运行在localhost:3000,服务端是localhost:5555,允许的跨域源应该是前端地址,同时添加allowCredentials支持认证头携带:

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
            .allowedOrigins("http://localhost:3000") // 改为前端地址
            .exposedHeaders("*")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowCredentials(true); // 支持携带JWT等认证信息
}

2. 让Spring Security放行OPTIONS预请求

预请求(OPTIONS)属于跨域必须的请求类型,需要在Security配置里明确放行:
修改securityFilterChain中的authorizeHttpRequests部分:

.authorizeHttpRequests((authorize)-> authorize
        .dispatcherTypeMatchers(DispatcherType.ERROR, DispatcherType.OPTIONS).permitAll() // 添加OPTIONS放行
        .requestMatchers(
            "/api/v1/auth/**",
            "/swagger-ui/**",
            "/swagger",
            "/swagger-ui.html"
        )
        .permitAll()
        .anyRequest()
        .authenticated()
)

3. 避免JWT过滤器拦截OPTIONS请求

登录接口正常是因为它无需认证,但/api/v1/article需要JWT,检查你的JwtAuthenticationFilter,确保它跳过OPTIONS请求:
在doFilterInternal方法开头添加判断:

if ("OPTIONS".equals(request.getMethod())) {
    response.setStatus(HttpServletResponse.SC_OK);
    return;
}

4. 验证CORS配置是否生效

用Postman发送OPTIONS请求到http://localhost:5555/api/v1/article,检查响应头是否包含以下字段:

  • Access-Control-Allow-Origin: http://localhost:3000
  • Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
  • Access-Control-Allow-Headers: *

如果这些头存在,说明CORS配置生效,问题可能出在认证环节;如果不存在,检查WebMvcConfiguration是否被Spring正确扫描(比如包路径是否在SpringBoot启动类的扫描范围内)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 05:43:14