springboot项目中 前端浏览器访问时遇到跨域请求问题CORS怎么解决?has been blocked by CORS policy

文章目录

    • 现象
    • 解决方案
      • [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. 在生产环境中的最佳实践)

现象

前端浏览器访问时,报错:

复制代码
Access to fetch at 'http://localhost:8080/api/signature/generate' from origin 'http://127.0.0.1:5500' ![has been blocked by CORS policy](https://i-blog.csdnimg.cn/direct/a6551b463e514483b4a7647469c87caf.png)
: 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 中是推荐的做法。

相关推荐
纪莫4 分钟前
A公司一面:类加载的过程是怎么样的? 双亲委派的优点和缺点? 产生fullGC的情况有哪些? spring的动态代理有哪些?区别是什么? 如何排查CPU使用率过高?
java·java面试⑧股
naice35 分钟前
我对github的图片很不爽了,于是用AI写了一个图片预览插件
前端·javascript·git
天蓝色的鱼鱼39 分钟前
Element UI 2.X 主题定制完整指南:解决官方工具失效的实战方案
前端·vue.js
风一样的树懒41 分钟前
死信队列:你在正确使用么?
后端
RoyLin44 分钟前
TypeScript设计模式:门面模式
前端·后端·typescript
小奋斗1 小时前
千量数据级别的数据统计分析渲染
前端·javascript
JavaGuide1 小时前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户3721574261351 小时前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源1 小时前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
weiwenhao1 小时前
关于 nature 编程语言
人工智能·后端·开源