文章目录
- 
- 现象
- 解决方案
- 
- [1. **全局配置 CORS**](#1. 全局配置 CORS)
- [2. **使用 `@CrossOrigin` 注解**](#2. 使用 @CrossOrigin注解)
- [3. **配置 Spring Security**](#3. 配置 Spring Security)
- [4. **自定义 CORS 过滤器**](#4. 自定义 CORS 过滤器)
 
- [`Spring Security 6.x 及其后续版本解决方案`](#Spring Security 6.x 及其后续版本解决方案)
- 
- [1. 使用 `SecurityFilterChain` 配置 CORS](#1. 使用 SecurityFilterChain配置 CORS)
- [2. 重要配置说明](#2. 重要配置说明)
- [3. 在生产环境中的最佳实践](#3. 在生产环境中的最佳实践)
 
- [1. 使用 `SecurityFilterChain` 配置 CORS](#1. 使用 
 
现象
前端浏览器访问时,报错:

Access to fetch at 'http://localhost:8080/api/signature/generate' from origin 'http://127.0.0.1:5500' 
: 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.解决方案
在 Spring Boot 项目中解决前端浏览器访问的 CORS (Cross-Origin Resource Sharing) 问题,可以通过以下几种方式来实现:
1. 全局配置 CORS
你可以通过配置类来全局设置 CORS 规则。这种方式适用于你希望为所有的控制器和端点设置统一的 CORS 配置。
示例代码:
            
            
              java
              
              
            
          
          import org.springframework.context.annotation.Bean;
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 WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000") // 允许的前端地址
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许的方法
                .allowedHeaders("*") // 允许的头部信息
                .allowCredentials(true); // 是否允许携带凭证
    }
}2. 使用 @CrossOrigin 注解
你可以在控制器方法或控制器类上使用 @CrossOrigin 注解来设置 CORS 策略。这种方式适用于你只希望为特定的端点设置 CORS 配置。
示例代码:
            
            
              java
              
              
            
          
          import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class MyController {
    @CrossOrigin(origins = "http://localhost:3000")
    @GetMapping("/data")
    public String getData() {
        return "This is CORS-enabled data.";
    }
}你也可以在控制器类上使用 @CrossOrigin 注解,这样会对该类下的所有方法生效:
            
            
              java
              
              
            
          
          import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:3000")
public class MyController {
    @GetMapping("/data")
    public String getData() {
        return "This is CORS-enabled data.";
    }
}3. 配置 Spring Security
如果你的项目中使用了 Spring Security,你还需要在 Spring Security 的配置中设置 CORS。
示例代码:
            
            
              java
              
              
            
          
          import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()
            .authorizeRequests()
            .anyRequest().authenticated(); // 配置你的安全规则
    }
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:3000")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
                        .allowedHeaders("*")
                        .allowCredentials(true);
            }
        };
    }
}4. 自定义 CORS 过滤器
你也可以定义一个自定义的 CORS 过滤器来处理跨域请求。
示例代码:
            
            
              java
              
              
            
          
          import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import org.springframework.stereotype.Component;
@Component
public class SimpleCorsFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        response.setContentType("text/html;charset=UTF-8");
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
    }
}选择适合你项目需求的方式来配置 CORS,确保前端能够成功访问你的后端接口。
Spring Security 6.x 及其后续版本解决方案
在 Spring Security 6.x 及其后续版本中,cors() 方法已经被弃用,因此需要通过更现代的方式配置 CORS。可以直接通过 SecurityFilterChain 结合 CorsFilter 进行配置。
以下是基于 Spring Boot 3.3.2 和 Spring Security 的跨域配置示例:
1. 使用 SecurityFilterChain 配置 CORS
        
            
            
              java
              
              
            
          
          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.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 配置跨域过滤器
        http
            .csrf().disable() // 禁用 CSRF
            .authorizeHttpRequests(authz -> authz
                .anyRequest().authenticated() // 根据需要配置权限
            )
            .addFilter(corsFilter()); // 添加自定义的 CORS 过滤器
        return http.build();
    }
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 允许客户端携带凭证(如 Cookies)
        config.addAllowedOriginPattern("*"); // 允许所有域名,生产环境可以改为特定域名
        config.addAllowedHeader("*"); // 允许所有请求头
        config.addAllowedMethod("*"); // 允许所有 HTTP 方法(GET, POST, PUT, DELETE 等)
        
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}2. 重要配置说明
- config.addAllowedOriginPattern("*"):这个方法用于允许所有来源的请求,- addAllowedOriginPattern替代了以前的- addAllowedOrigin,并更灵活地支持正则表达式。
- addAllowedMethod("*"):允许所有 HTTP 请求方法。
- addAllowedHeader("*"):允许所有请求头。
3. 在生产环境中的最佳实践
为了确保安全,在生产环境中,建议将 addAllowedOriginPattern 限制为特定的域名,而不是使用 "*" 来允许所有来源。这样可以避免潜在的安全风险。
这个配置通过 CorsFilter 实现了跨域支持,而不是依赖已被弃用的 .cors() 方法。这种方式在 Spring 3.3.2 和 Spring Security 中是推荐的做法。