在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中指定的方法,或者GET,HEAD,POST如果@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 的基本步骤:
-
打开 Nginx 配置文件,通常位于
/etc/nginx/nginx.conf或/etc/nginx/conf.d/目录下的某个文件中。 -
在
server块或具体的location块中,添加配置来定义允许的源(Access-Control-Allow-Origin)、HTTP 方法(Access-Control-Allow-Methods)等 CORS 头信息。 -
重启 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 的跨域请求,并指定了允许的方法和头信息。对于实际的 POST 和 GET 请求,也添加了类似的头信息。
请注意,配置应该根据你的具体需求进行调整。例如,如果你想要允许多个来源,可能需要一些额外的逻辑来检查请求头中的 Origin 并动态地设置 Access-Control-Allow-Origin。
使用 Nginx 实现 CORS 可以使得跨域策略的管理更加集中,在使用微服务架构或多个后端服务时尤其方便。不过,值得注意的是,确保 Nginx 的 CORS 设置与你的应用安全策略保持一致是非常重要的。
相关文章:
在Spring Boot中如何处理跨域请求(CORS)?
什么是跨域? 跨域(Cross-Origin Resource Sharing,CORS)是一种机制,它允许在 Web 页面上运行的脚本能够请求从不同源(域名、协议或端口)的资源。在浏览器安全策略中,有一条称为同源…...
好就业三种专业#信息安全#云计算#网络工程
一、信息安全专业 根据2021年网络安全宣传周白皮书的观察结果,网络安全产业对于人才的需求正以高速增长的趋势呈现,当前网络安全行业存在着巨大的人才缺口,平均供求比例约为1:2。这一现象导致了资深人才的储备不足,并且新人才的培…...
electron-builder打包
打包配置: "build": {"appId": "cc11001100.electron.example-001", // 程序包名"copyright": "CC11001100", // 版权相关信息"productName": "example-001", // 安装包文件名"direct…...
SQLiteC/C++接口详细介绍sqlite3_stmt类(四)
返回:SQLite—系列文章目录 上一篇:SQLiteC/C接口详细介绍sqlite3_stmt类(三) 下一篇:SQLiteC/C接口详细介绍sqlite3_stmt类(五) 7. sqlite3_bind_parameter_count函数 sqlite3_bind_param…...
微信小程序自定义组件
微信小程序中的自定义组件是指在微信小程序中创建的可重用的、可复用的组件,它可以被多个页面使用。自定义组件可以帮助我们提高开发效率,提高代码的可维护性和可重用性。以下是微信小程序中自定义组件的使用方法: 一. 创建自定义组件 首先…...
python练习3
用户登录注册案例 while True: print("\t\t\t英雄商城登录界面\n") print("~*"*38) print("\t\t\t1.用户登录\n") print("\t\t\t2.用户注册\n") print("\t\t\t3.退出系统\n") print("~*"*38) choice input("…...
docker离线安装并修改存储目录
docker下载 根据cpu选择不同版本,正常x86就选x86_64 下载地址:https://download.docker.com/linux/static/stable/ docker安装 tar -zxvf arm-docker-25.0.4.tgz sudo cp docker/* /usr/bin/ rm -rf docker/* mkdir /etc/docker vi /etc/docker/daemo…...
【云原生 • Kubernetes】认识 k8s、k8s 架构、核心实战
文章目录 Kubernetes基础概念1. 是什么2. 架构2.1 工作方式2.2 组件架构 3. k8s组件创建集群步骤一 基础环境步骤二 安装kubelet、kubeadm、kubectl步骤三 主节点使用kubeadm引导集群步骤四 副节点加入主节点步骤五 部署dashboard Kubernetes核心实战1. 资源创建方式2. Namespa…...
墨菲安全在软件供应链安全领域阶段性总结及思考
向外看:墨菲安全在软件供应链安全领域的一些洞察、思考、行动 洞察 现状&挑战: 过去开发安全体系是无法解决软件供应链安全问题的;一些过去专注开发安全领域的厂商正在错误的引导行业用开发安全思维解决软件供应链安全问题,治…...
智慧公厕:卫生、便捷、安全的新时代厕所变革
在城市快速发展的背景下,公共厕所的建设和管理变得越来越重要。智慧公厕作为厕所变革的一项全新举措,通过建立公共厕所全面感知监测系统,以物联网、互联网、大数据、云计算、自动化控制技术为支撑,实现对公共厕所的智能化管理和运…...
Idea 不能创建JDK1.8的spring boot项目
由于https://start.springboot.io/ 不支持JDK1.8,那么我们需要换idea的springboot创建源,需要换成 https://start.aliyun.com,这也是网上大部分教程说的,但是我这边会报这样的错误: Initialization failed for https:…...
【docker】Docker学习收集
写在前面 新公司开发使用docker来部署和统一大家的开发环境,故再次记录好用的学习链接和自己遇到的奇怪问题 实用链接 Docker教程详细 常用命令 个例问题 Q: docker在终端多开,A终端的修改会影响B吗 A: 会...
LoRa模块在野外科研与环境保护中的角色:科技守护自然之宝
随着科技的不断发展,LoRa(低功耗广域网)模块在野外科研与环境保护中正发挥着越来越重要的作用。其卓越的通信能力、低功耗特性以及良好的穿透能力,为科学家和环保人士提供了一种先进的技术手段,有助于更深入、更全面地…...
全国媒体公关服务资源分析,媒体邀约资源包括哪些?-51媒体网
传媒如春雨,润物细无声,大家好,我是51媒体网胡老师。 全国媒体公关服务资源分析是一个涵盖多方面的复杂议题,主要涉及到不同媒体类型、传播渠道、以及公关策略等多个维度。在当前媒体环境下,媒体公关服务资源主要包括…...
【Springboot3+Mybatis】文件上传阿里云OSS 基础管理系统CRUD
文章目录 一、需求&开发流程二、环境搭建&数据库准备三、部门管理四、员工管理4.1 分页(条件)查询4.2 批量删除员工 五、文件上传5.1 介绍5.2 本地存储5.3 阿里云OSS1. 开通OSS2. 创建存储空间Bucket 5.4 OSS快速入门5.5 OSS上传显示文件 六、配置文件6.1 yml配置6.2 C…...
音频和视频标签
音频用audio标签 controls表示控制栏 loop循环播放音频 autoplay自动播放(浏览器基于隐私一般不支持) <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Com…...
计算机组成原理 运算器的组成实验
一、实验目的 1、认识模拟器 2、熟悉模拟器构建 3、运算器的组成的实验 二、实验内容 1、仿真面板 2、数据通路总体图 3、解释ALU、DR1H、DR1L、DR2H、DR2L、SW_BUS 4、运算器的组成的实验。 (1)连接模拟板线路组成运算器,展示仿真面板图,数据通…...
SpringBoot 启用 Https,生成 jks 自签证书
使用 Java 提供的工具生成 jks 自签证书 keytool 是 Java Development Kit (JDK) 中的一个工具,用于管理公钥和私钥对以及相关的证书。以下命令用于生成一个密钥对并将其存储在密钥库中: keytool -genkeypair -alias www.example.com -keyalg RSA -key…...
微服务day04(下) -- SpringAMQP
SpringAMQP SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。 SpringAmqp的官方地址:Spring AMQP SpringAMQP提供了三个功能: 自动声明队列、交换机及其绑定关系 基于注解的…...
RK3568平台开发系列讲解(pinctrl篇)pinctrl 子系统函数操作集
🚀返回专栏总目录 文章目录 一、pinctrl_ops二、pinctrl_ops三、pinconf_ops沉淀、分享、成长,让自己和他人都能有所收获!😄 在 pinctrl_desc 结构体中总共有三个函数操作集, 具体内容如下所示: const struct pinctrl_ops *pctlops; // 引脚控制操作函数指针 const...
【AGI测试验证黄金法则】:20年AI系统工程师首曝7大不可绕过的验证陷阱
第一章:AGI测试验证的范式革命 2026奇点智能技术大会(https://ml-summit.org) 传统AI系统测试依赖静态数据集、预设指标与确定性边界,而AGI具备跨域泛化、自主目标建模与持续元认知能力,使黑盒评估、对抗扰动鲁棒性测试和价值对齐验证面临根…...
不止于读取:用CT117E-M4的四个按键玩出花样(状态机/长短按/组合键)
突破基础交互:用状态机重构CT117E-M4的按键逻辑设计 当你在嵌入式系统开发中遇到需要处理复杂用户交互的场景时,四个物理按键往往显得捉襟见肘。传统轮询式按键检测虽然简单直接,但面对菜单导航、参数调整、功能确认等多样化需求时࿰…...
GME-Qwen2-VL-2B-Instruct精彩案例:广告素材与文案匹配度智能评分实践
GME-Qwen2-VL-2B-Instruct精彩案例:广告素材与文案匹配度智能评分实践 1. 项目背景与价值 在数字营销时代,广告素材与文案的匹配度直接影响转化效果。传统的人工审核方式效率低下,且主观性强,难以保证一致性。GME-Qwen2-VL-2B-I…...
云原生应用开发实践
云原生应用开发实践:构建高效可靠的现代应用 在数字化转型的浪潮中,云原生技术已成为企业构建高效、可扩展应用的核心方法论。云原生应用开发不仅能够充分利用云计算的优势,还能通过微服务、容器化和自动化运维等实践,显著提升开…...
技术顶尖却始终赚不到大钱:程序员最容易忽略的那门“手艺”
在技术一线,越来越多程序员把“精通Java”“刷LeetCode”“深挖源码”当成职业护城河。年薪五十万、技术专家头衔、公司核心项目一把抓,看起来前途无量。可真正到职业天花板时,却发现自己和65岁只剩105美元的肯德基上校桑德斯上校陷入了同一个…...
协方差交叉:在相关性未知时,如何实现保守且鲁棒的多传感器数据融合?
1. 协方差交叉:当传感器"各说各话"时如何达成共识 想象一下你在玩一个多人协作游戏,每个队友都从不同角度观察同一个目标,但他们的报告可能存在误差甚至矛盾。这时候作为队长,你既不能完全相信某一个人,也不…...
Flutter 入门第九课:本地存储实战(SharedPreferences + 文件 + SQLite)
这节课是 Flutter 实现数据本地持久化的核心,也是 APP 开发的必备能力 —— 解决「重启后数据丢失」的问题,实现登录状态保存、离线缓存、历史记录、本地配置等核心业务场景。我们会系统学习 Flutter 三大本地存储方案,按轻量→中等→重量级划…...
《英雄无敌:上古纪元》评测:经典回合制策略游戏的回归之作
开发任何一款新的《魔法门之英雄无敌》都是一场巨大的冒险。这个系列对许多玩家来说早已不只是回合制策略的经典,更是近乎无法超越的这种游戏的标杆。正因如此,每一部新作都会受到粉丝们的严苛审视:它不仅要是一款好游戏,还必须证…...
Pixel Aurora Engine 构建数字人素材库:快速生成多样化人物肖像与表情
Pixel Aurora Engine 构建数字人素材库:快速生成多样化人物肖像与表情 1. 数字人素材生产的行业痛点 在虚拟主播、游戏NPC和在线教育数字人项目中,高质量的人物素材需求正呈现爆发式增长。传统制作方式面临着三大核心挑战: 成本高昂&#…...
Windows上安装Android应用的终极指南:APK Installer完整教程
Windows上安装Android应用的终极指南:APK Installer完整教程 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 在Windows电脑上直接安装Android应用曾经是件复…...
