Spring: 在SpringBoot项目中解决前端跨域问题

news2024/11/25 16:37:45

这里写目录标题

  • 一、什么是跨域问题
  • 二、浏览器的同源策略
  • 三、SpringBoot项目中解决跨域问题的5种方式:使用CORS
    • 1、自定 web filter 实现跨域(全局跨域)
    • 2、重写 WebMvcConfigurer(全局跨域)
    • 3、 CorsFilter(全局跨域)
    • 4、使用@CrossOrigin注解 (局部跨域)

一、什么是跨域问题

跨域问题,也称为跨域资源共享(CORS,Cross-Origin Resource Sharing)问题,主要出现在Web开发中,尤其是当前端代码和后端代码分别部署在不同的域名下时。由于浏览器的同源策略限制,一个域的网页中通过JavaScript发起的跨域请求会被浏览器阻止,除非响应报文包含了正确的CORS相关头部信息。

跨域问题主要涉及到以下几个关键点:

  • 同源与跨源:如果两个页面的协议、域名和端口都相同,则它们是同源的;否则,它们是跨源的。

  • 浏览器限制:浏览器默认会阻止跨源请求,除非后端服务器明确允许这种请求。

  • CORS头部:为了允许跨源请求,后端服务器需要在响应中包含特定的CORS头部,如Access-Control-Allow-Origin。

  • 预检请求:对于某些类型的跨域请求(如带有自定义头部的请求或PUT/DELETE等请求),浏览器会先发送一个OPTIONS请求进行预检,以检查服务器是否允许这种请求。

解决跨域问题的方法有多种,包括但不限于:

  • 使用CORS:在后端服务器上配置CORS策略,允许特定的跨源请求。
  • 使用代理服务器:在前端和后端之间设置一个代理服务器,前端请求发送到代理服务器,再由代理服务器转发到后端服务器。
  • JSONP:一种古老的跨域技术,利用<script>标签没有跨域限制的特性来实现跨域请求。但JSONP只支持GET请求,且存在安全隐患,而且前后端都需要写相应的代码。
  • 设置document.domain:对于主域名相同而子域名不同的情况,可以通过设置document.domain来实现跨域。

在实际开发中,应根据具体需求和场景选择合适的跨域解决方案。

二、浏览器的同源策略

同源策略是浏览器的一个安全功能,它阻止从一个源加载的文档或脚本与另一个源的资源进行交互。这是为了防止恶意文档读取或修改另一个源加载的资源。同源策略限制了不同源之间的DOM访问、AJAX请求以及Web存储访问等。当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。此外浏览器是否启用跨域保护机制是又后端的响应Response来决定的
在这里插入图片描述

三、SpringBoot项目中解决跨域问题的5种方式:使用CORS

1、自定 web filter 实现跨域(全局跨域)

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Component
public class MyCorsFilter implements Filter {
    private static Logger LOGGER = LoggerFactory.getLogger(MyCorsFilter.class);
    @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", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "*");

        LOGGER.info("reponse cors: Access-Control-Allow-Origin={}" +
                ", Access-Control-Allow-Methods={}" +
                ", Access-Control-Allow-Credentials={}" +
                ", Access-Control-Allow-Headers={}",
                response.getHeader("Access-Control-Allow-Origin"),
                response.getHeader("Access-Control-Allow-Methods"),
                response.getHeader("Access-Control-Allow-Credentials"),
                response.getHeader("Access-Control-Allow-Headers"));
        chain.doFilter(req, res);
    }
}

2、重写 WebMvcConfigurer(全局跨域)

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://example.com") // 允许哪些源的请求  
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的HTTP方法  
                .allowedHeaders("*") // 允许的头部  
                .allowCredentials(true) // 是否允许发送cookies  
                .maxAge(168000); // 预检请求的缓存时间(秒)  
    }  
}

3、 CorsFilter(全局跨域)

CorsFilter 是 Java Spring 框架中用于处理跨域请求(CORS,Cross-Origin Resource Sharing)的过滤器。通过使用 CorsFilter,你可以配置你的 Spring 应用以允许跨域请求,从而避免浏览器因同源策略而阻止这些请求。下面是一个简单的 Spring Boot 应用中如何使用 CorsFilter 的例子:

  • 添加依赖(如果你使用 Spring Boot,这个依赖可能已经包含在内):
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
</dependency>
  • 创建 CorsFilter:
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;  
  
@Configuration  
public class CorsConfig {  
  
    @Bean  
    public CorsFilter corsFilter() {  
        CorsConfiguration config = new CorsConfiguration();  
        config.setAllowedOrigins(Arrays.asList("*")); // 允许所有源进行访问  
        config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); // 允许的方法  
        config.setAllowCredentials(true); // 是否发送cookie  
        config.setMaxAge(168000); // 预检间隔时间  
  
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();  
        source.registerCorsConfiguration("/**", config); // 对所有路径应用 CORS 配置  
  
        return new CorsFilter(source);  
    }  
}

在这个例子中,我们创建了一个 CorsFilter Bean,它允许来自任何源的请求,并允许 GET、POST、PUT 和 DELETE 方法。我们还设置了 AllowCredentials 为 true,这意味着浏览器可以发送带有凭据(如 cookies、HTTP 认证及客户端 SSL 证明等)的请求。最后,我们设置了 CORS 预检请求的缓存时间为 168000 秒(即 2 天)。

  • 启动你的 Spring Boot 应用。现在,你的应用应该能够处理跨域请求了。请注意,出于安全考虑,你不应该在生产环境中将 AllowedOrigins 设置为 *,除非你完全信任所有可能的源。通常,你会将 AllowedOrigins 设置为一个特定的域名列表。

4、使用@CrossOrigin注解 (局部跨域)

@CrossOrigin 是 Spring Framework 提供的一个注解,用于解决跨域资源共享(CORS)问题。通过在类或者方法上使用 @CrossOrigin 注解,你可以轻松地为 Spring MVC 控制器开启 CORS 支持。这个注解允许你指定哪些域、HTTP 方法以及头部可以被允许进行跨域请求。

  • 在控制器类上使用
    可以直接在控制器类上使用 @CrossOrigin 注解,以允许整个控制器的所有方法都接受跨域请求:
import org.springframework.web.bind.annotation.CrossOrigin;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
@CrossOrigin(origins = "http://example.com", methods = {RequestMethod.GET, RequestMethod.POST})  
public class MyController {  
    // ... 控制器方法 ...  
}
  • 在单个方法上使用
    可以将 @CrossOrigin 注解添加到特定的控制器方法上,以仅允许该方法的跨域请求:
import org.springframework.web.bind.annotation.CrossOrigin;  
import org.springframework.web.bind.annotation.GetMapping;  
import org.springframework.web.bind.annotation.RestController;  
  
@RestController  
public class MyController {  
  
    @GetMapping("/someMethod")  
    @CrossOrigin(origins = "http://example.com")  
    public String someMethod() {  
        // ... 方法实现 ...  
        return "Response";  
    }  
}

使用 @CrossOrigin 注解时,你可以指定多个允许的源,方法,头部等。这提供了一种灵活的方式来控制哪些跨域请求应该被允许。需要注意的是,出于安全考虑,你应该仔细考虑允许哪些源进行跨域请求,并限制允许的 HTTP 方法和头部。

最后,确保你的 Spring Boot 应用已经包含了 Spring Web 的依赖,并且你的控制器类和方法已经正确地映射到了相应的 URL 路径。这样,当来自允许源的请求到达时,Spring MVC 就会自动处理 CORS 预检请求,并在响应中包含正确的 CORS 头部。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1557536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

稀碎从零算法笔记Day34-LeetCode:最小栈

感谢耶稣&#xff0c;笔者又过了一天“复活节”。月末斩杀一道Hard画上句号 题型&#xff1a;栈、模拟数据结构 链接&#xff1a;155. 最小栈 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 设计一个支持 push &#xff0c;pop &#xff0c;…

适用于 Windows 的 6 个最佳视频转换器

视频转换器可以帮助您在设备上转换和播放不受支持的视频格式。它还可以方便地减小视频文件大小、以通用格式组织所有视频或与其他人共享文件以在不同设备上播放。 Windows 有大量视频转换器可供选择。虽然有些是免费的&#xff0c;但其他一些则提供迎合专业用户的高级功能。在…

Pycharm选择使用Anaconda环境中的Pytorch 失败解决办法之一

前几日想要复现一篇论文&#xff0c;结果给配的台式机完全禁不住&#xff0c;老是报溢出&#xff0c;慢都没事&#xff0c;溢出就很难受了&#xff0c;因此想用自己笔记本的GPU来训练。 安装以后遇到一个问题&#xff1a; Anaconda里创建了环境&#xff0c;安装好了对应pytor…

AR智能眼镜解决方案_MTK平台安卓主板硬件芯片方案开发

AR智能眼镜&#xff0c;是一个可以让现场作业更智能的综合管控设备。采用移动互联网、大数据和云计算等技术&#xff0c;现场数据的采集与分析&#xff1b;同时实现前端现场作业和后端管理的实时连动、信息的同步传输与存储。让前端现场作业更加智能&#xff0c;后端管理更加高…

再次加深理解Java中的并发编程

目录 一、线程、进程、程序 二、线程状态 三、线程的七大参数 四、lock与synchronized锁机制 一&#xff09;、lock与synchronized锁区别 二&#xff09;、synchronized锁原理 三&#xff09;、Lock锁原理 五、synchronized锁升级原理 一&#xff09;、锁升级基础知识 …

【Web】NSSCTF Round#20 Basic 两道0解题的赛后谈

目录 前言 baby-Codeigniter 组合拳&#xff01; 前言 本想着说看看go的gin框架就睡了的&#xff0c;r3师傅提醒说赛题环境已经上了&#xff0c;那不赶紧研究下&#x1f600; 主要来谈谈做题的心路历程 baby-Codeigniter 拿到题目的第一反应应该是&#xff1a;“什么是C…

C之易错注意点转义字符,sizeof,scanf,printf

目录 前言 一&#xff1a;转义字符 1.转义字符顾名思义就是转换原来意思的字符 2.常见的转义字符 1.特殊\b 2. 特殊\ddd和\xdd 3.转义字符常错点----计算字符串长度 注意 &#xff1a; 如果出现\890,\921这些的不是属于\ddd类型的&#xff0c;&#xff0c;不是一个字符…

SOA-面向服务架构

SOA-面向服务架构 1.概述2.SOA的设计原则包括&#xff1a;3. SOA实现方法1.Web Service2. 服务注册表3. 企业服务总线 细讲 超赞笔记 1.概述 SOA &#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09;&#xff0c;从应用和原理的角度&#xff0c;目前有2种…

书生·浦语大模型-第一节课笔记

视频总结 23年发布的模型在一些材料中归位指令微调模型&#xff0c;后面逐渐升级应该已经是train的模型了 技术报告总结 InternLM2 Technical Report 评测与特点 6 dimensions and 30 benchmarks, long-context modeling, and open-ended subjective evaluations长文本…

【软件工程】概要设计

1. 导言 1.1 目的 该文档的目的是描述学生成绩管理系统的概要设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统结构简介 系统接口设计 数据设计 模块设计 界面设计 本文的预期读者是&#xff1a; 项目开发人员 项目管理人员 项目评测人员&#xff08;…

C++:数据类型—字符串(11)

字符串就是包含多个字符组成的一个串 比如字符a,b&#xff0c;单个字符就是字符 那么"hello world" 就是一串字符组成的一个字符串 注意字符要在双引号里引用上&#xff0c;而字符一般都是单引号引用 在c中有两种定义字符串的方法&#xff0c;一个是原始c语言的定义方…

swift中的autoreleasepool(自动释放池)有用么?

想到一个问题 swift中的autoreleasepool(自动释放池)有用么? 我们进行验证一下 首先我们写一个加载图片的方法,保证会真正用到真实的IMP内存func loadBigData(string: String?) {if let path Bundle.main.path(forResource: "big", ofType: "png") {for…

二十四种设计模式与六大设计原则(二):【门面模式、适配器模式、模板方法模式、建造者模式、桥梁模式、命令模式】的定义、举例说明、核心思想、适用场景和优缺点

接上次博客&#xff1a;二十四种设计模式与六大设计原则&#xff08;一&#xff09;&#xff1a;【策略模式、代理模式、单例模式、多例模式、工厂方法模式、抽象工厂模式】的定义、举例说明、核心思想、适用场景和优缺点-CSDN博客 目录 门面模式【Facade Pattern】 定义 举…

vitess执行计划缓存 测试

打开执行计划器缓存&#xff1a; sysbench /usr/local/share/sysbench/oltp_write_only.lua --mysql-host127.0.0.1 --mysql-port15306 --mysql-userroot --mysql-password --mysql-dbcustomer --report-interval10 100s sysbench /usr/local/share/sysbench/oltp_read_only.l…

9.动态规划——1.从递归到动态规划

例题——N阶楼梯上楼问题 分析 大事化小&#xff1a;爬N层有F(N)种可能&#xff0c;有 F ( N ) F ( N − 1 ) F ( N − 2 ) F(N)F(N-1)F(N-2) F(N)F(N−1)F(N−2)小事化了&#xff1a; F ( 1 ) 1 &#xff0c; F ( 2 ) 2 F(1)1&#xff0c;F(2)2 F(1)1&#xff0c;F(2)2 …

小白从0学习ctf(web安全)

文章目录 前言一、baby lfi&#xff08;bugku-CTF&#xff09;1、简介2、解题思路1、解题前置知识点2、漏洞利用 二、baby lfi 2&#xff08;bugku-CTF&#xff09;1.解题思路1、漏洞利用 三、lfi&#xff08;bugku CTF&#xff09;1、解题思路1、漏洞利用 总结 前言 此文章是…

【Redis】Redis 生产问题。如何确保缓存和数据库数据的一致性? 常见的缓存更新策略?

目录 缓存穿透 缓存穿透解决办法 缓存击穿 击穿解决办法&#xff1f; 缓存穿透和缓存击穿的区别&#xff1f; 缓存雪崩 雪崩解决办法&#xff1f; 如何确保缓存和数据库数据的一致性&#xff1f; 常见的缓存更新策略&#xff1f; 缓存穿透 定义&#xff1a;缓存穿透说…

npm mongoose包下载冲突解决之道

我在新电脑下载完项目代码后,运行 npm install --registryhttps://registry.npm.taobao.org 1运行就报错&#xff1a; npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: lowcode-form-backend1.0.0 npm …

rabbitMQ的基础操作与可视化界面

当你安装好RabbitMq时&#xff0c;可以 尝试一下&#xff0c;这些命令 启动rabbitMQ服务 #启动服务 systemctl start rabbitmq-server #查看服务状态 systemctl status rabbitmq-server #停止服务 systemctl stop rabbitmq-server #开机启动服务 systemctl enable rabbitmq-…

代码随想录——移动零(Leetcode283)

题目链接 使用快慢指针思想 class Solution {public void moveZeroes(int[] nums) {int slow 0;for(int fast 0; fast < nums.length; fast){if(nums[fast] ! 0){nums[slow] nums[fast];}}while(slow < nums.length){nums[slow] 0;}} }