在Spring Boot中如何处理跨域请求(CORS)?

什么是跨域?

跨域(Cross-Origin Resource Sharing,CORS)是一种机制,它允许在 Web 页面上运行的脚本能够请求从不同源(域名、协议或端口)的资源。在浏览器安全策略中,有一条称为同源策略(Same-Origin Policy)的规则用以限制从一个源加载的文档或脚本如何与另一个源的资源进行交互。同源策略旨在防止恶意文档窃取数据、破坏用户的隐私等安全问题。

同源策略规定,如果两个 URL 的协议、域名和端口号都相同,则它们具有相同的源(Origin)。例如:

  • http://example.com/app1 和 http://example.com/app2 是同源的。
  • http://example.com 和 http://sub.example.com 是跨域的。
  • http://example.com 和 https://example.com 是跨域的。
  • http://example.com:80 和 http://example.com:8080 是跨域的。

如果你的 Web 应用中包含从其他源获取资源的需求(例如,前端应用从不同域名的 API 服务器请求数据),同源策略将默认阻止这种跨源 HTTP 请求。为了解决这个问题,可以使用 CORS。

CORS 通过在服务器端返回特定的 HTTP 头来告诉浏览器允许本次请求。这些 CORS 响应头部信息让浏览器了解服务器允许的来源、HTTP 方法以及其他一些安全设置。

下面是一些常见的 CORS 响应头:

  • Access-Control-Allow-Origin: 指定了可以访问资源的 URI。可以是具体的 URI 或 *(代表任意域名)。
  • Access-Control-Allow-Methods: 指定了服务器支持的所有跨域请求的方法(如 GET, POST, PUT, DELETE 等)。
  • Access-Control-Allow-Headers: 用在对预请求的响应中,表示实际请求可以包含的 HTTP 头列表。
  • Access-Control-Allow-Credentials: 表示是否可以将请求的响应暴露给前端的 JavaScript 代码。当值为 true 时,表示可以。

当浏览器执行跨源 HTTP 请求时,根据请求的类型,它可能首先发起一个预请求(preflight request),这是一种使用 OPTIONS 方法的 HTTP 请求,用来检查真实请求是否安全。服务器必须响应预请求并指明哪些 HTTP 方法和头信息是允许的。

在 Spring 框架中,你可以使用 @CrossOrigin 注解在控制器或请求映射上声明 CORS 配置,或者使用全局配置来定义 CORS 策略。

跨域通常是 Web 开发中的一个常见问题,尤其是在前后端分离的架构模式中,了解如何正确地配置和使用 CORS 是非常重要的。

注解介绍

@CrossOrigin 注解是 Spring 框架提供的一种途径,用以在控制器级别或单独的处理器方法(handler method)上启用 CORS(Cross-Origin Resource Sharing)。这个注解可以用于支持跨源请求,允许你指定哪些域可以访问应用的响应。

你可以使用 @CrossOrigin 注解来设置如下 CORS 相关的配置选项:

  • origins:一个或多个允许跨域请求的域。默认为 *,表示允许所有域的请求。
  • methods:一个或多个允许的 HTTP 方法。默认为 @RequestMapping 中指定的方法,或者 GETHEADPOST 如果 @RequestMapping 没有指定。
  • allowedHeaders:一个或多个允许的请求头。
  • exposedHeaders:一个或多个在响应中可以暴露给客户端的响应头。
  • maxAge:预请求缓存的最大时间(以秒为单位)。默认为 1800 秒(30 分钟)。
  • allowCredentials:是否允许用户凭证。默认为 true

这里有一个使用 @CrossOrigin 注解的例子:

@RestController
@RequestMapping("/api")
public class MyApiController {// 应用于单个控制器方法@CrossOrigin(origins = "https://example.com")@GetMapping("/users")public List<User> getUsers() {// ...return userList;}// 应用于整个控制器类@CrossOrigin(origins = "*", maxAge = 3600)@GetMapping("/projects")public List<Project> getProjects() {// ...return projectList;}
}

在上面的示例中,getUsers 方法中的 @CrossOrigin 注解指定了只有来自 https://example.com 的跨域请求才能访问该接口。而 getProjects 方法的 @CrossOrigin 注解由于没有指定 origins,默认允许来自所有域的请求,并且指定了预请求的最大缓存时间为 3600 秒(1 小时)。

如果你想为整个控制器类的所有方法启用相同的 CORS 配置,可以将 @CrossOrigin 注解放在类级别,如下所示:

@CrossOrigin(origins = "https://example.com", maxAge = 3600)
@RestController
@RequestMapping("/api")
public class MyApiController {// 控制器方法
}

此时,类级别的 @CrossOrigin 配置将应用于控制器中的所有处理器方法。

此外,你也可以通过全局配置来设置 CORS,这通常在 Spring 应用的配置类(如使用 @Configuration 注解的类)中完成。全局 CORS 配置会影响整个应用中所有控制器的所有跨域请求。

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("https://example.com").allowedMethods("GET", "POST", "PUT", "DELETE").allowedHeaders("*").allowCredentials(true).maxAge(3600);}
}

在上面的全局 CORS 配置中,所有控制器中的所有路由都将允许来自 https://example.com 的跨域请求,并且允许特定的 HTTP 方法。这种全局配置适合于当你希望整个应用有一致的跨域策略时使用。

请注意,类级别或方法级别的 @CrossOrigin 注解的设置会覆盖全局 CORS 配置。

前后端分离的单页面应用,后面接口如何配置跨域?

对于前后端分离的单页面应用(SPA),后端接口配置允许跨域的 origins 应该是前端应用所部署的 URL。这种配置使得浏览器可以允许从前端应用的源向后端发起跨域请求。

例如,假设你的前端应用部署在 https://my-spa-frontend.com,而后端 API 部署在 https://my-backend-api.com。为了让前端应用能够正常地从后端 API 请求数据,后端应该在 CORS 配置中的 origins 中指定 https://my-spa-frontend.com

@CrossOrigin(origins = "https://my-spa-frontend.com")
@RestController
public class MyApiController {// API 方法
}

这样配置后,当浏览器从 https://my-spa-frontend.com 发出对 https://my-backend-api.com 的 AJAX 请求时,浏览器将识别到后端 API 允许来自 https://my-spa-frontend.com 的跨域请求,并允许这些请求成功访问资源。

如果你的前端应用有多个部署环境(如开发、测试和生产环境),你可能需要根据环境来设置不同的 origins

@CrossOrigin(origins = {"https://dev-frontend.com", "https://test-frontend.com", "https://my-spa-frontend.com"})
@RestController
public class MyApiController {// API 方法
}

或者,在实际部署时,你可以使用环境变量或配置文件来动态设置 CORS 的 origins,使其适应不同的部署环境。

还要注意,对于开发环境,有时开发人员会使用特殊的值 *,这表示允许所有域的请求,这在开发阶段是方便的,但出于安全考虑,通常不推荐在生产环境中使用此设置:

// 只在开发环境中使用
@CrossOrigin(origins = "*")
@RestController
public class MyApiController {// API 方法
}

总之,origins 应该包含允许访问后端 API 的前端应用的 URL,从而为前后端分离的单页面应用启用跨域请求。在生产环境中,应该使用具体的域名而不是通配符 *,以确保应用的安全性。

其他方式

跨域(CORS)也可以在网关层实现,比如使用 Nginx。通常,这种方法可以更加集中和统一地管理跨域策略,并且可以减轻后端应用服务器的一些配置负担。

在 Nginx 中实现 CORS 的基本思路是在响应头中添加相应的 CORS 头信息。这些信息告诉浏览器,Nginx 服务允许来自特定原(origin)的跨域请求。

以下是在 Nginx 中配置 CORS 的基本步骤:

  1. 打开 Nginx 配置文件,通常位于 /etc/nginx/nginx.conf/etc/nginx/conf.d/ 目录下的某个文件中。

  2. server 块或具体的 location 块中,添加配置来定义允许的源(Access-Control-Allow-Origin)、HTTP 方法(Access-Control-Allow-Methods)等 CORS 头信息。

  3. 重启 Nginx 以应用更改。

下面是一个 Nginx 配置 CORS 的例子:

server {listen 80;server_name my-backend-api.com;location / {# 你的代理或其他配置# CORS 配置if ($request_method = 'OPTIONS') {add_header 'Access-Control-Allow-Origin' 'https://my-spa-frontend.com';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';add_header 'Access-Control-Allow-Credentials' 'true';add_header 'Content-Length' '0';add_header 'Content-Type' 'text/plain charset=UTF-8';add_header 'Access-Control-Max-Age' '1728000';return 204;}if ($request_method = 'POST') {add_header 'Access-Control-Allow-Origin' 'https://my-spa-frontend.com';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';add_header 'Access-Control-Allow-Credentials' 'true';}if ($request_method = 'GET') {add_header 'Access-Control-Allow-Origin' 'https://my-spa-frontend.com';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type';add_header 'Access-Control-Allow-Credentials' 'true';}}
}

在上述配置中,我们为 OPTIONS 请求添加了 CORS 预检(preflight)请求所需的响应头,允许来自 https://my-spa-frontend.com 的跨域请求,并指定了允许的方法和头信息。对于实际的 POSTGET 请求,也添加了类似的头信息。

请注意,配置应该根据你的具体需求进行调整。例如,如果你想要允许多个来源,可能需要一些额外的逻辑来检查请求头中的 Origin 并动态地设置 Access-Control-Allow-Origin

使用 Nginx 实现 CORS 可以使得跨域策略的管理更加集中,在使用微服务架构或多个后端服务时尤其方便。不过,值得注意的是,确保 Nginx 的 CORS 设置与你的应用安全策略保持一致是非常重要的。

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

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

相关文章

python 中怎样使用任意关键词实参?

在 Python 中&#xff0c;可以使用任意数量的关键字实参和任意关键字实参&#xff0c;也被称为 kwargs。 这允许你在函数调用时传递任意数量的关键字参数。 你可以使用任意数量的关键字实参&#xff08;Keyword Arguments&#xff09;和任意关键字实参&#xff08;Arbitrary Ke…

sonar接入maven项目

1、介绍 sonar是一款静态代码质量分析工具&#xff0c;支持Java、Python、PHP、JavaScript、CSS等25种以上的语言&#xff0c;而且能够集成在IDE、Jenkins、Git等服务中&#xff0c;方便随时查看代码质量分析报告。他有如下特性 (1) 检查代码是否遵循编程标准&#xff1a;如命…

走迷宫---dfs在矩阵图里的应用模板

题目描述如下&#xff1a; dfs算法解决迷宫问题的一个标准模板 &#xff0c;通过递归与回溯暴力遍历所有能走的点&#xff0c;并比较找出所有可行方案的最优解 解决这道问题的核心思想和组合数如出一辙&#xff0c;可以说是组合数的升级版 结合注释看dfs更清晰易懂&#xff0…

springcloud-Eureka注册中心

如果你要理解这个技术博客博客专栏 请先学习以下基本的知识&#xff1a; 什么是微服务什么是服务拆分什么是springcloud Springcloud为微服务开发提供了一个比较泛用和全面的解决框架&#xff0c;springcloud继承了spring一直以来的风格——不重复造轮子&#xff0c;里面很多的…

测试平台——前端框架

一、创建vue项目 npm init vitelatest web_class wylWYLdeMacBook-Air testplatform % npm init vitelatest web_class ✔ Select a framework: › Vue ✔ Select a variant: › JavaScriptScaffolding project in /Users/wyl/workspace/testplatform/web_class...Done. Now…

IoT 物联网场景中如何应对安全风险?——青创智通

工业物联网解决方案-工业IOT-青创智通 ​随着物联网&#xff08;IoT&#xff09;技术的快速发展&#xff0c;越来越多的设备、系统和应用被连接到互联网上&#xff0c;从而构建了一个庞大的物联网生态系统。然而&#xff0c;这种连接性也带来了前所未有的安全风险。在物联网场景…

Android Studio实现内容丰富的安卓校园公告助手

获取源码请点击文章末尾QQ名片联系&#xff0c;源码不免费&#xff0c;尊重创作&#xff0c;尊重劳动 093校园助手 1.开发环境 android stuido3.6 jak1.8 eclipse mysql tomcat 2.功能介绍 具体往下看第三节&#xff0c;功能截图 安卓端&#xff1a; 1.注册登录 2.校园公告列表…

微信小程序执行环境(微信端)与浏览器环境有何不同

微信小程序执行环境与浏览器环境有很多不同之处&#xff0c;以下是一些例子&#xff1a; 全局对象&#xff1a; 浏览器环境中的 JavaScript 有一个全局对象 window&#xff0c;而微信小程序中的 JavaScript 没有 window 对象&#xff0c;取而代之的是 wx 对象&#xff0c;wx …

持续集成平台 02 jenkins plugin 插件

拓展阅读 Devops-01-devops 是什么&#xff1f; Devops-02-Jpom 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件 代码质量管理 SonarQube-01-入门介绍 项目管理平台-01-jira 入门介绍 缺陷跟踪管理系统&#xff0c;为针对缺陷管理、任务追踪和项目管理的商业…

系统架构设计师考试-专业英语

词汇含义access存取active-matrix主动矩阵adapter适配器&#xff0c;转换器adapter cards适配卡agents代理analog signals模拟信号animations动画applets程序arithmetic operations算术运算array数组&#xff0c;阵列assembly汇编&#xff0c;安装&#xff0c;装配asynchronous…

C#面:简述 LINQ

C# 中的 LINQ&#xff08;Language Integrated Query&#xff09;是集成查询语言&#xff0c;它允许我们在编写代码时使用类似于 SQL 的查询语法来查询和操作各种数据源&#xff0c;如集合、数据库、XML 等。 LINQ 的主要特点包括&#xff1a; 统一的查询语法&#xff1a;LIN…

【pip 安装pymssql报错】 Failed to build pymssql

在使用pip install pymssql安装pymssql时报如下图的错误&#xff1b; 报错截图 2&#xff09;查找资料说pip<3.0版本 &#xff0c;我也试了&#xff0c;不行。 你们也可以试一试&#xff1a;pip install"pymssql<3.0" 3&#xff09;我的成功方式&#xff1…

全量知识系统 概要设计(SmartChat回复)

以下是根据我给出的 系统概要 “提要和纪要”&#xff0c;SmartChat给出的概要设计。我给出的“提要和纪要”可参考链接&#xff1a; https://blog.csdn.net/ChuanfangChen/article/details/136861822 -------------------------------- 概要设计文档 1. 简介 全量知识系统…

浅谈 电脑和车的对比

https://www.zhihu.com/question/547115488 电脑CPU与汽车发动机有哪些相同点与不同点&#xff1f; - 知乎 就想机械硬盘一样 我们的技术可能达不到 但是我们可以弯道超车 比如长江存储的SSD可以取代 以前的机械硬盘

流畅的 Python 第二版(GPT 重译)(八)

第十五章&#xff1a;关于类型提示的更多内容 我学到了一个痛苦的教训&#xff0c;对于小程序来说&#xff0c;动态类型很棒。对于大型程序&#xff0c;你需要更加纪律严明的方法。如果语言给予你这种纪律&#xff0c;而不是告诉你“嗯&#xff0c;你可以做任何你想做的事情”&…

JavaScript:TypeScript网上笔记总结

文章目录 1:基础类型数值型 number字符串类型 string布尔类型 boolean数组类型 Array元组 Tuple任意类型 anyvoid&#xff1a;与any类型相反&#xff0c;表示没有类型null 、undefined类型never类型枚举类型类型断言类型推论&#xff5c;类型别名 2:接口3:类&#xff08;不咋用…

WordPress Wholesale Market 插件 任意文件读取漏洞复现

0x01 产品简介 WordPress plugin Wholesale Market 是一个woocommerce扩展插件&#xff0c;使您的商店能够创建批发用户&#xff0c;并通过设置产品的批发价格。 0x02 漏洞概述 WordPress plugin Wholesale Market 2.2.1之前版本存在路径遍历漏洞&#xff0c;该漏洞源于没有…

海南省月降水量分布数据

海南省位于中国南端&#xff0c;海南岛地处热带北缘&#xff0c;属热带季风气候&#xff0c;长夏无冬。海南省雨量充沛&#xff0c;年降水量在1000毫米&#xff5e;2600毫米之间&#xff0c;年平均降水量为1639毫米&#xff0c;有明显的多雨季和少雨季。每年的5&#xff5e;10月…

Django资源路径问题

学习过django框架的应该了解后端有static静态文件&#xff0c;media媒体文件&#xff0c;还有一些其他的配置文件&#xff0c;那么在整个web服务中每个区域访问资源的路径有什么区别呢 前端模版中src 一般本地项目的src都是写项目中的相对路径或者根据电脑磁盘的绝对路径 而在…

鸿蒙Harmony应用开发—ArkTS-转场动画(组件内隐式共享元素转场)

geometryTransition用于组件内隐式共享元素转场&#xff0c;在组件显示切换过程中提供平滑过渡效果。通用transition机制提供了opacity、scale等转场动效&#xff0c;geometryTransition通过id绑定in/out组件(in指入场组件、out指出场组件)&#xff0c;使得组件原本独立的trans…