第五章 跨域资源共享(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不仅能解决开发过程中的常见跨域问题,还能有效提升系统的安全性。


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

相关文章
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
101 3
|
17天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
105 45
|
10天前
|
开发框架 中间件 Java
如何处理跨域资源共享(CORS)的 OPTIONS 请求?
处理 CORS 的 OPTIONS 请求的关键是正确设置响应头,以告知浏览器是否允许跨域请求以及允许的具体条件。根据所使用的服务器端技术和框架,可以选择相应的方法来实现对 OPTIONS 请求的处理,从而确保跨域资源共享的正常进行。
|
10天前
|
JavaScript 前端开发 API
跨域资源共享(CORS)的工作原理是什么?
跨域资源共享(CORS)通过浏览器和服务器之间的这种交互机制,在保证安全性的前提下,实现了跨域资源的访问,使得不同源的网页能够合法地获取和共享服务器端的资源,为现代Web应用的开发提供了更大的灵活性和扩展性。
|
13天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
29 1
|
15天前
|
XML 安全 PHP
PHP与SOAP Web服务开发:基础与进阶教程
本文介绍了PHP与SOAP Web服务的基础和进阶知识,涵盖SOAP的基本概念、PHP中的SoapServer和SoapClient类的使用方法,以及服务端和客户端的开发示例。此外,还探讨了安全性、性能优化等高级主题,帮助开发者掌握更高效的Web服务开发技巧。
|
18天前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
31 2
|
2月前
|
小程序 前端开发 中间件
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
本文介绍了如何在ThinkPHP框架中配置跨域请求,使用了TP内置的跨域类`\think\middleware\AllowCrossDomain::class`。文章还讨论了小程序和web网页在跨域请求格式上的区别,并提供了解决方案,包括修改跨域中间件源码以支持`Origin`和`token`。此外,还介绍了微信小程序跨域请求的示例和web网页前端发送Axios跨域请求的请求拦截器配置。
ThinkPHP 配置跨域请求,使用TP的内置跨域类配置,小程序和web网页跨域请求的区别及格式说明
WK
|
18天前
|
安全 Java 编译器
C++和Java哪个更适合开发web网站
在Web开发领域,C++和Java各具优势。C++以其高性能、低级控制和跨平台性著称,适用于需要高吞吐量和低延迟的场景,如实时交易系统和在线游戏服务器。Java则凭借其跨平台性、丰富的生态系统和强大的安全性,广泛应用于企业级Web开发,如企业管理系统和电子商务平台。选择时需根据项目需求和技术储备综合考虑。
WK
26 0
|
1月前
|
设计模式 测试技术 持续交付
开发复杂Web应用程序
【10月更文挑战第3天】开发复杂Web应用程序
39 2