第五章 跨域资源共享(CORS):现代Web开发中的关键机制

简介: 第五章 跨域资源共享(CORS):现代Web开发中的关键机制

引言

在现代Web开发中,不同源之间数据交换的需求日益增长。然而,出于安全原因,浏览器对从一个域向另一个域发起请求有着严格的限制,这就是同源策略(Same-Origin Policy)。


然而,同源策略限制了后端访问接口必须与网站一致!这就非常不灵活,尤其现在web应用多为多端应用,又同时需要多个地址的服务的情况下。(这里是重点)

为了解决这一问题,并实现安全、灵活的跨域通信,跨域资源共享(Cross-Origin Resource Sharing, 简称CORS)应运而生。本文将深入探讨CORS的工作原理、配置方法及其在实际应用中的重要性。

一、同源策略与跨域限制

1. 概念

同源策略(Same-Origin Policy)是浏览器为保护用户信息安全而实施的一种安全机制。在Web开发领域,同源策略规定了来自同一来源的文档或脚本可以相互读取和交互数据,而不同源则不能直接进行这样的操作。这里的“源”由协议、域名和端口三部分组成,如果这三者完全相同,则认为两个资源是同源的。

2. 举例说明

  1. 同源示例
  • 这两个URL具有相同的协议(HTTPS)、相同的域名(www.example.com)和相同的端口(默认HTTP/HTTPS端口,即443),因此它们被认为是同源的,这个请求将被允许执行。
  1. 非同源示例
  • 当前网页地址为 https://www.example.com/index.html。
  • 页面尝试发送一个AJAX请求到 http://api.other-example.com/data
  • 这两个URL的协议不同(一个是HTTPS,另一个是HTTP),或者域名不同(www.example.com与api.other-example.com),因此它们被视为不同源。
  • 根据同源策略,浏览器将会阻止此跨域请求,除非服务器配置了支持跨域资源共享(CORS)并明确允许从www.example.com发起请求。

同源策略旨在防止恶意网站通过JavaScript读取其他站点的敏感信息,例如cookies或其他存储在本地的数据。对于需要进行跨域通信的应用场景,可以通过CORS、JSONP等技术实现安全可控的数据交换。

二、跨域资源共享(CORS)

1. 概念

首先要明确的是CORS是一种W3C标准(非常重要,是浏览器和服务器共同去完成的一套http请求机制),允许服务器明确声明哪些外部域可以访问其资源。通过CORS,服务器能够设置允许哪些HTTP请求方法、头信息和自定义响应头被其他域使用。


跨域资源共享(Cross-Origin Resource Sharing,CORS)是一种允许网页从不同源(domain、协议或端口不一致)获取资源的机制。在Web开发中,由于浏览器的安全策略——同源策略(Same-Origin Policy),一个源下的文档或脚本默认情况下不能访问另一个源的资源。然而,在实际应用中,往往需要跨域请求以实现数据共享和服务调用。

2. CORS工作原理与举例说明

1. CORS请求类型

  • 简单请求:对于GET、POST等简单HTTP方法以及某些标准头部字段的请求,可以被视为简单请求。浏览器会自动在请求头中添加Origin字段,标识请求发起者的源。

示例:

GET /data HTTP/1.1
Host: api.example.com
Origin: https://www.example.net

服务器收到请求后,会在响应头中返回Access-Control-Allow-Origin来指定哪些源可以访问该资源。

2. 预检请求(Preflight Request)

对于非简单请求,如使用自定义头部字段或PUT、DELETE等其他HTTP方法的请求,浏览器会先发送一个OPTIONS预检请求询问服务器是否接受该跨域请求。

示例:

OPTIONS /data HTTP/1.1
Host: api.example.com
Origin: https://www.example.net
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header

-- Response --
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://www.example.net
Access-Control-Allow-Methods: PUT, POST, DELETE
Access-Control-Allow-Headers: X-Custom-Header

3. 服务器配置

服务器根据接收到的请求和自身的CORS策略,通过设置特定的响应头信息来决定是否允许这次跨域请求。

例如,服务器可以通过设置如下响应头允许来自https://www.example.net的请求:

Access-Control-Allow-Origin: https://www.example.net


4. CORS安全控制

CORS还提供了其他一些响应头用于更精细的权限控制,如:

  • Access-Control-Allow-Credentials 控制是否允许携带凭据(如 Cookies 或 HTTP 认证信息)进行跨域请求。
  • Access-Control-Max-Age 设置预检请求结果的有效期,减少重复预检次数。

三、CORS请求类型与流程

1. 简单请求

  • 对于GET、POST等简单HTTP方法以及一些特定的头部字段,浏览器可以直接发起跨域请求,无需预检。

浏览器会在请求头中自动添加Origin字段表明来源域,服务器根据此信息决定是否放行请求。

在浏览器发起跨域请求时,对于非简单请求(如包含了自定义头部、PUT、DELETE等方法的请求)和所有预检请求(OPTIONS),

  • 浏览器会自动在请求头中添加一个Origin字段。这个字段包含的是当前发出请求的页面所在的源信息,即协议+域名+端口。

如果一个网页加载自 https://example.com,当它尝试向 https://api.example.net 发送一个跨域请求时,浏览器会在请求头中插入如下内容:

Origin: https://example.com

服务器收到请求后,可以通过检查Origin头来判断请求是否来自允许访问的源。如果服务器配置了CORS策略,并且Access-Control-Allow-Origin响应头中包含了与请求头中的Origin相匹配的源,那么该请求将被放行;否则,请求会被服务器拒绝。

举个例子,服务器可以这样设置其CORS策略以允许来自https://example.com的请求:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com

2. 预检请求(Preflight Request)

  • 当请求方法不是简单的GET/POST或者包含自定义头部时,浏览器会先发送一个OPTIONS方法的预检请求来询问服务器。
  • 服务器收到预检请求后,若返回的响应头中包含了Access-Control-Allow-OriginAccess-Control-Allow-Methods等相关字段并允许当前源,则后续的实际请求会被正常处理。

预检请求(Preflight Request)是CORS机制中的一种特殊请求,用于非简单请求(例如使用了自定义头部字段、PUT、DELETE等方法的请求)在实际发送前向服务器询问是否允许该跨域请求。以下是一个关于预检请求的例子,包括客户端发起请求和服务器端响应:

3. 客户端JavaScript示例

// 使用fetch API 发起一个带有自定义头部的PUT请求
fetch('https://api.example.com/data', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'X-Custom-Header': 'custom-value'
  },
  body: JSON.stringify({ key: 'value' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

在此例中,由于我们设置了自定义头部X-Custom-Header并使用了PUT方法,浏览器会先发送一个OPTIONS预检请求。

4. 服务器端响应示例(以Node.js + Express为例)

const express = require('express');
const app = express();

app.options('/data', (req, res) => { // 处理预检请求
  res.set({
    'Access-Control-Allow-Origin': 'https://www.example.net', // 允许特定源
    'Access-Control-Allow-Methods': 'PUT, POST, DELETE, OPTIONS', // 允许的方法列表
    'Access-Control-Allow-Headers': 'Content-Type, X-Custom-Header', // 允许的头部
    'Access-Control-Max-Age': 86400 // 预检结果缓存时间(单位秒)
  });

  if (req.headers.origin) {
    res.setHeader('Access-Control-Allow-Credentials', true); // 允许携带凭据(如 Cookies)
  }

  res.status(204).send(); // 预检请求不需要返回数据体,仅需设置正确的响应头
});

app.put('/data', (req, res) => {
  // 实际处理PUT请求逻辑
});

// ...其他路由...

app.listen(3000, () => console.log('Server started on port 3000'));

当客户端发起上述跨域PUT请求时,浏览器首先发送一个OPTIONS预检请求到服务器。如果服务器的预检响应表明允许该请求,则浏览器才会继续发送实际的PUT请求。

四、CORS响应头详解

  • Access-Control-Allow-Origin: 必需字段,指定允许接收请求的源。
  • Access-Control-Allow-Methods: 指定允许的方法列表,如GET, POST, PUT, DELETE等。
  • Access-Control-Allow-Headers: 允许客户端发送的非标准请求头。
  • Access-Control-Allow-Credentials: 表示是否允许携带cookie和认证信息进行跨域请求。
  • Access-Control-Max-Age: 设置预检请求结果的有效期,减少重复预检的次数。

五、CORS配置实例

在服务器端(如Node.js的Express框架),可以通过中间件实现CORS:

const express = require('express');
const app = express();

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*'); // 允许所有源
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE'); // 允许的方法
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); // 允许的头部
  if (req.method === 'OPTIONS') {
    res.send(204); // 预检请求则直接返回204状态码
  } else {
    next(); // 其他请求继续执行路由处理函数
  }
});

// ... 添加你的路由逻辑 ...

六、CORS实践与安全性考量

尽管CORS极大地增强了Web应用程序的功能性和灵活性,但它也引入了一些潜在的安全风险,比如可能泄露敏感信息。因此,在实施CORS策略时务必谨慎,避免过于宽松的设置,如只允许特定可信的源访问资源,同时对允许的方法和头部进行严格控制。


总结来说,跨域资源共享作为现代Web开发的重要组成部分,对于构建高效、安全且具有丰富交互体验的应用至关重要。理解并正确配置CORS不仅能解决开发过程中的常见跨域问题,还能有效提升系统的安全性。


衷心感谢您阅读至此,若您在本文中有所收获,恳请您不吝点赞、评论或分享,您的支持是我们持续创作高质量内容的动力源泉。同时,也诚挚邀请您关注本博客,以便获取更多前端开发与设计相关的深度解析和实战技巧,我们期待与您共同成长,一起探索前端世界的无限精彩!

相关文章
|
2月前
|
前端开发 JavaScript 应用服务中间件
前端跨域问题解决Access to XMLHttpRequest at xxx from has been blocked by CORS policy
跨域问题是前端开发中常见且棘手的问题,但通过理解CORS的工作原理并应用合适的解决方案,如服务器设置CORS头、使用JSONP、代理服务器、Nginx配置和浏览器插件,可以有效地解决这些问题。选择合适的方法可以确保应用的安全性和稳定性,并提升用户体验。
822 90
|
2月前
|
关系型数据库 MySQL 数据库
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
TIS 是一款基于Web-UI的开源大数据集成工具,通过与人大金仓Kingbase的深度整合,提供高效、灵活的实时数据集成方案。它支持增量数据监听和实时写入,兼容MySQL、PostgreSQL和Oracle模式,无需编写复杂脚本,操作简单直观,特别适合非专业开发人员使用。TIS率先实现了Kingbase CDC连接器的整合,成为业界首个开箱即用的Kingbase CDC数据同步解决方案,助力企业数字化转型。
315 5
基于Flink CDC 开发,支持Web-UI的实时KingBase 连接器,三大模式无缝切换,效率翻倍!
|
2月前
|
JSON 缓存 前端开发
对CORS(跨域)的一些见解
CORS(跨域资源共享)是W3C标准,用于解决AJAX跨源请求限制。浏览器与服务器需共同支持CORS,浏览器自动处理请求头,开发者无需额外操作。CORS分为简单请求与非简单请求:简单请求满足特定条件(如方法为GET/POST/HEAD且头信息有限制),浏览器直接发送;非简单请求需先进行“预检”请求(OPTIONS方法),确认服务器允许后才发送实际请求。服务器回应需包含Access-Control-Allow-Origin等字段,以控制跨域访问权限。
79 10
|
2月前
|
移动开发 前端开发 API
鸿蒙web加载本地网页资源异常
在鸿蒙NEXT Api 12中,为解决Web组件加载本地资源(如图片、CSS等)失败的问题,我们采用拦截机制。具体步骤如下: 1. **替换路径**:通过正则表达式将HTML和CSS中的资源路径替换为带有标记的URL(如`http://local`),以便后续识别。 2. **拦截与返回**:在资源加载时,拦截带有标记的URL,读取对应的本地文件并返回给Web组件。此过程确保了本地资源能正确加载和显示。 代码实现包括路径替换、资源拦截及响应构建,确保Web页面能够顺利加载本地资源。
149 7
|
2月前
|
机器学习/深度学习 开发框架 API
Python 高级编程与实战:深入理解 Web 开发与 API 设计
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧以及数据科学和机器学习。本文将深入探讨 Python 在 Web 开发和 API 设计中的应用,并通过实战项目帮助你掌握这些技术。
|
6月前
|
存储 前端开发 JavaScript
如何在项目中高效地进行 Web 组件化开发
高效地进行 Web 组件化开发需要从多个方面入手,通过明确目标、合理规划、规范开发、加强测试等一系列措施,实现组件的高效管理和利用,从而提高项目的整体开发效率和质量,为用户提供更好的体验。
158 63
|
6月前
|
开发框架 搜索推荐 数据可视化
Django框架适合开发哪种类型的Web应用程序?
Django 框架凭借其强大的功能、稳定性和可扩展性,几乎可以适应各种类型的 Web 应用程序开发需求。无论是简单的网站还是复杂的企业级系统,Django 都能提供可靠的支持,帮助开发者快速构建高质量的应用。同时,其活跃的社区和丰富的资源也为开发者在项目实施过程中提供了有力的保障。
231 62
|
6月前
|
开发框架 中间件 Java
如何处理跨域资源共享(CORS)的 OPTIONS 请求?
处理 CORS 的 OPTIONS 请求的关键是正确设置响应头,以告知浏览器是否允许跨域请求以及允许的具体条件。根据所使用的服务器端技术和框架,可以选择相应的方法来实现对 OPTIONS 请求的处理,从而确保跨域资源共享的正常进行。
314 61
|
5月前
|
前端开发 安全 JavaScript
2025年,Web3开发学习路线全指南
本文提供了一条针对Dapp应用开发的学习路线,涵盖了Web3领域的重要技术栈,如区块链基础、以太坊技术、Solidity编程、智能合约开发及安全、web3.js和ethers.js库的使用、Truffle框架等。文章首先分析了国内区块链企业的技术需求,随后详细介绍了每个技术点的学习资源和方法,旨在帮助初学者系统地掌握Dapp开发所需的知识和技能。
2025年,Web3开发学习路线全指南
|
5月前
|
安全 Java 应用服务中间件
SpringBoot:CORS是什么?SpringBoot如何解决跨域问题?
CORS是Web开发中常见且重要的机制,SpringBoot通过提供注解、全局配置和过滤器等多种方式来解决跨域问题。选择适合的方式可以帮助开发者轻松处理跨域请求,提高应用的灵活性和安全性。
275 2

热门文章

最新文章