跨域资源共享 (CORS) 是 Web 浏览器实施的一项重要安全机制,用于保护用户免受潜在恶意脚本的攻击。然而,这也是开发人员(尤其是 Web 开发新手)感到沮丧的常见原因。小编在此将向大家解释它存在的原因,并提供处理与 CORS 相关问题的策略。
什么是 CORS?
CORS 是由 Web 浏览器实现的一项安全功能,用于控制从资源来源域之外的其他域对网页上的资源(如 API 或字体)的访问。
同源策略
要理解 CORS,我们首先需要了解同源策略。此策略是 Web 浏览器中的一项基本安全措施,用于限制从一个来源加载的文档或脚本如何与来自另一个来源的资源进行交互。来源由协议、域和端口的组合定义。
例如:
- https://example.com/page1且https://example.com/page2有相同的起源。
- https://example.com并且http://example.com有不同的来源(不同的协议)
- https://example.com并且https://api.example.com具有不同的来源(不同的子域)。
为什么存在 CORS
引入 CORS 是为了允许服务器指定哪些来源可以访问其资源,从而以受控的方式放宽同源策略。这对于经常需要向托管在不同域上的 API 发出请求的现代 Web 应用程序至关重要。
常见 CORS 错误
开发人员在尝试从 Web 应用程序向其他域上的 API 发出请求时经常会遇到 CORS 错误。典型的 CORS 错误可能如下所示:
Access to fetch at 'https://api.example.com/data' from origin 'https://myapp.com'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource.
CORS 的工作原理
当 Web 应用程序发出跨源请求时:
- 浏览器发送请求时附带一个Origin标头,指定请求页面的来源。
- 然后服务器可以响应:
- 指定Access-Control-Allow-Origin允许哪些来源的标头。
- 控制允许的方法、标头等的其他 CORS 标头。
3. 如果服务器的响应不包含适当的 CORS 标头,浏览器将阻止响应。
解决 CORS 问题
1. 服务器端配置
解决 CORS 问题的最正确方法是配置服务器以发送正确的 CORS 标头。这通常涉及:
- 设置Access-Control-Allow-Origin标题以指定允许的来源。
- 根据需要配置其他 CORS 标头(例如Access-Control-Allow-Methods,Access-Control-Allow-Headers)。
使用 Express 的 Node.js 示例:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors({
origin: 'https://myapp.com'
}));
2. 使用代理
如果您无法控制服务器,则可以设置代理服务器来添加必要的 CORS 标头。这通常在开发环境中完成。
使用 Create Vue App 的代理功能的示例:
在package.json:
{
"proxy": "https://api.example.com"
}
3. JSONP(仅适用于 GET 请求)
JSONP(带填充的 JSON)是一种较旧的技术,它可以通过使用不受同源策略约束的脚本标签来绕过 GET 请求的 CORS。
function handleResponse(data) {
console.log(data);
}
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleResponse';
document.body.appendChild(script);
注意:JSONP 被认为是过时的,并且不如正确的 CORS 实现安全。
最佳实践
- 了解安全隐患:不要盲目绕过 CORS。它的存在是有原因的。
- 使用特定来源:避免*在Access-Control-Allow-Origin生产中使用。指定确切的允许来源。
- 使用特定于环境的配置:对开发和生产环境有不同的 CORS 设置。
- 处理预检请求:对于非简单请求,正确处理 OPTIONS 请求。
- 牢记安全:请记住,CORS 是由浏览器强制执行的。服务器端安全措施仍然是必要的。
最后
如果您遇到 CORS 问题,第一步是确定您是否可以控制服务器。如果可以,实施适当的 CORS 标头是最好的解决方案。如果没有,请考虑使用代理,或者作为简单 GET 请求的最后手段,使用 JSONP。