Java跨域案例如何配置解决

wen java案例 27

本文目录导读:

Java跨域案例如何配置解决

  1. 核心概念:什么是跨域?
  2. 方案一:Spring Boot 微服务后端
  3. 方案二:Spring Cloud Gateway 网关层
  4. 方案三:Java Web 原生过滤器(非 Spring 框架)
  5. 常见问题排查
  6. 最终建议

Java 中解决跨域问题的配置方案,主要取决于你的应用架构,下面整理了三种最常见的场景(Spring Boot、Spring Cloud Gateway、以及原始的 Servlet Filter),你可以直接参考。

核心概念:什么是跨域?

浏览器出于安全考虑,有同源策略,当请求的协议、域名、端口三者中任意一个与当前页面不同,就会产生跨域。

解决跨域的常用思路是服务器在响应头中返回 Access-Control-Allow-Origin 等字段,告诉浏览器“这个请求我允许”,这被称为 CORS(跨域资源共享)


方案一:Spring Boot 微服务后端

如果你的后端是 Spring Boot,这是最常用、最推荐的方式。

方式 A:全局配置(推荐,适合整个项目的所有接口)

添加一个配置类,实现 WebMvcConfigurer,并重写 addCorsMappings 方法。

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.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 允许所有路径
                .allowedOriginPatterns("*") // 允许所有来源(用 patterns 更安全,支持通配符)
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的方法
                .allowedHeaders("*") // 允许所有请求头
                .allowCredentials(true) // 允许携带 cookie
                .maxAge(3600); // 预检请求的有效期,单位秒,1小时内不用再发预检
    }
}

注意allowedOriginPatterns("*")allowedOrigins("*") 更灵活,尤其是在开启了 allowCredentials(true) 时。

方式 B:注解方式(适合某个特定 Controller 或方法)

在 Controller 类或方法上使用 @CrossOrigin 注解。

import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:3000") // 允许指定域名
public class UserController {
    @GetMapping("/user")
    public String getUser() {
        return "Hello, CORS!";
    }
}

方案二:Spring Cloud Gateway 网关层

如果你使用了微服务网关,可以在网关层面统一处理,避免在每个微服务里重复配置。

application.ymlbootstrap.yml 中配置跨域过滤器:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOriginPatterns: "*"       # 允许的来源
            allowedMethods: "*"             # 允许的方法
            allowedHeaders: "*"             # 允许的请求头
            allowCredentials: true          # 允许携带凭证
            maxAge: 3600

方案三:Java Web 原生过滤器(非 Spring 框架)

如果你的项目是原始的 Servlet 应用,没有使用 Spring 框架,可以写一个过滤器:

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*"); // 允许所有来源(生产环境建议指定具体域名)
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        response.setHeader("Access-Control-Max-Age", "3600");
        // 处理预检请求:如果是 OPTIONS 请求,直接返回 200
        String method = ((javax.servlet.http.HttpServletRequest) req).getMethod();
        if ("OPTIONS".equalsIgnoreCase(method)) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }
        chain.doFilter(req, res);
    }
    @Override
    public void init(FilterConfig filterConfig) {}
    @Override
    public void destroy() {}
}

然后在 web.xml 中注册这个过滤器。


常见问题排查

问题 1:前端报错 The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'

  • 原因:你设置了 allowCredentials(true)allowedOrigins("*"),这两者不能同时使用(这是浏览器安全限制)。
  • 解决:将 allowedOrigins("*") 改为 allowedOriginPatterns("*")(Spring Boot 2.4+ 支持),或者指定具体的域名。

问题 2:预检请求(OPTIONS)返回 403

  • 原因:Spring Security 拦截了 OPTIONS 请求。
  • 解决:在 Spring Security 配置中放行 OPTIONS 请求和 OPTIONS 方法。
// 在 SecurityConfig 中
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .cors() // 开启 CORS 支持
        .and()
        .csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 放行 OPTIONS 请求
        .anyRequest().authenticated();
}

问题 3:使用了 Nginx 或反向代理

如果你的请求经过了 Nginx,还需要确认 Nginx 是否正确转发了 OPTIONS 请求,或者是否在 Nginx 层面配置了 CORS(有时 Nginx 的配置会覆盖后端的 CORS 设置)。

最终建议

  • 开发环境:直接使用 allowedOriginPatterns("*")@CrossOrigin 快速调试。
  • 生产环境allowedOriginPatterns 限定为前端部署的具体域名(如 https://www.yourdomain.com),不要使用通配符。
  • 网关与微服务:只在网关层配置 CORS,微服务内部不再单独配置,这样职责更清晰。

抱歉,评论功能暂时关闭!