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 中是推荐的做法。

相关推荐
aygh4 分钟前
Java八股文复习指南
java·面试·八股文·后端开发
luanma1509806 分钟前
Laravel 8.X重磅特性全解析
前端·javascript·vue.js·php·lua
小则又沐风a13 分钟前
类和对象(C++)---上
java·c++·算法
季明洵18 分钟前
动态规划及背包问题
java·数据结构·算法·动态规划·背包问题
kyriewen22 分钟前
为什么我的代码在测试环境跑得好好的,一到用户电脑就崩?原来凶手躲在地址栏旁边
前端·javascript·chrome
祭曦念25 分钟前
学Rust3次都放弃?这篇文章帮你避开90%的新手劝退
后端
Wect25 分钟前
LeetCode 215. 数组中的第K个最大元素:大根堆解法详解
前端·算法·typescript
ETA827 分钟前
面试官:说说事件冒泡与委托?这是我见过最透彻的回答
前端·javascript
C澒31 分钟前
PC 桌面富应用:速分客户端
前端·c++·electron·web app
侠客行031732 分钟前
Tomcat 从陌生到熟悉
java·tomcat·源码阅读