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

相关推荐
迷雾漫步者1 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
xlsw_2 小时前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
神仙别闹3 小时前
基于java的改良版超级玛丽小游戏
java
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
黄油饼卷咖喱鸡就味增汤拌孜然羊肉炒饭3 小时前
SpringBoot如何实现缓存预热?
java·spring boot·spring·缓存·程序员
暮湫3 小时前
泛型(2)
java
超爱吃士力架3 小时前
邀请逻辑
java·linux·后端
南宫生3 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论