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

本文涉及的产品
.cn 域名,1个 12个月
简介: 第五章 跨域资源共享(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不仅能解决开发过程中的常见跨域问题,还能有效提升系统的安全性。


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

相关文章
|
12天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
68 3
|
2月前
|
小程序 前端开发 中间件
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
本文介绍了如何在ThinkPHP框架中配置跨域请求,使用了TP内置的跨域类`\think\middleware\AllowCrossDomain::class`。文章还讨论了小程序和web网页在跨域请求格式上的区别,并提供了解决方案,包括修改跨域中间件源码以支持`Origin`和`token`。此外,还介绍了微信小程序跨域请求的示例和web网页前端发送Axios跨域请求的请求拦截器配置。
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
|
18天前
|
设计模式 测试技术 持续交付
开发复杂Web应用程序
【10月更文挑战第3天】开发复杂Web应用程序
29 2
|
20天前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
38 3
|
2月前
|
数据可视化 图形学 UED
只需四步,轻松开发三维模型Web应用
为了让用户更方便地应用三维模型,阿里云DataV提供了一套完整的三维模型Web模型开发方案,包括三维模型托管、应用开发、交互开发、应用分发等完整功能。只需69.3元/年,就能体验三维模型Web应用开发功能!
249 8
只需四步,轻松开发三维模型Web应用
|
2月前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
97 6
|
2月前
|
存储 JSON API
实战派教程!Python Web开发中RESTful API的设计哲学与实现技巧,一网打尽!
在数字化时代,Web API成为连接前后端及构建复杂应用的关键。RESTful API因简洁直观而广受欢迎。本文通过实战案例,介绍Python Web开发中的RESTful API设计哲学与技巧,包括使用Flask框架构建一个图书管理系统的API,涵盖资源定义、请求响应设计及实现示例。通过准确使用HTTP状态码、版本控制、错误处理及文档化等技巧,帮助你深入理解RESTful API的设计与实现。希望本文能助力你的API设计之旅。
59 3
|
2月前
|
JSON API 数据库
从零到英雄?一篇文章带你搞定Python Web开发中的RESTful API实现!
在Python的Web开发领域中,RESTful API是核心技能之一。本教程将从零开始,通过实战案例教你如何使用Flask框架搭建RESTful API。首先确保已安装Python和Flask,接着通过创建一个简单的用户管理系统,逐步实现用户信息的增删改查(CRUD)操作。我们将定义路由并处理HTTP请求,最终构建出功能完整的Web服务。无论是初学者还是有经验的开发者,都能从中受益,迈出成为Web开发高手的重要一步。
57 4
|
2月前
|
开发框架 JSON 缓存
震撼发布!Python Web开发框架下的RESTful API设计全攻略,让数据交互更自由!
在数字化浪潮推动下,RESTful API成为Web开发中不可或缺的部分。本文详细介绍了在Python环境下如何设计并实现高效、可扩展的RESTful API,涵盖框架选择、资源定义、HTTP方法应用及响应格式设计等内容,并提供了基于Flask的示例代码。此外,还讨论了版本控制、文档化、安全性和性能优化等最佳实践,帮助开发者实现更流畅的数据交互体验。
63 1
|
2月前
|
JSON API 开发者
惊!Python Web开发新纪元,RESTful API设计竟能如此性感撩人?
在这个Python Web开发的新纪元里,RESTful API的设计已经超越了简单的技术实现,成为了一种追求极致用户体验和开发者友好的艺术表达。通过优雅的URL设计、合理的HTTP状态码使用、清晰的错误处理、灵活的版本控制以及严格的安全性措施,我们能够让RESTful API变得更加“性感撩人”,为Web应用注入新的活力与魅力。
48 3