CORS实现跨域的过程

当加上 CORS 之后,从发起到请求正式成功一般会经历以下过程:

简单请求(以 GET、POST 等简单方法且无特殊请求头的请求为例)

  1. 发起请求:客户端(通常是浏览器)向跨域的服务器发送请求,例如使用 fetchXMLHttpRequest 等 API。请求头中会包含 Origin 字段,它表示请求发起的源,包括协议、域名和端口号。
  2. 服务器接收请求:服务器接收到请求后,会检查 Origin 字段。然后根据自身的 CORS 配置,判断该源是否被允许访问。
  3. 服务器响应:如果 Origin 是允许的,服务器会在响应头中添加 Access - Control - Allow - Origin 字段,其值为允许的源(可以是具体的源,也可能是 * 表示允许所有源)。同时,可能还会添加其他相关的 CORS 响应头,如 Access - Control - Allow - Credentials(如果涉及到跨域携带凭证)等。然后将响应数据发送给客户端。
  4. 客户端处理响应:浏览器接收到响应后,检查 Access - Control - Allow - Origin 等 CORS 相关头信息。如果这些头信息表明请求是被允许的,浏览器就会正常处理响应数据,将其传递给前端应用程序进行进一步处理和展示。

复杂请求(如 PUT、DELETE 方法或带有自定义请求头的请求)

  1. 发起预检请求(OPTIONS) :客户端首先会发送一个预检请求,使用 OPTIONS 方法。请求头中包含 Origin 字段,同时还会有 Access - Control - Request - Method 字段,用于告知服务器实际请求将使用的方法(如 PUTDELETE 等),以及 Access - Control - Request - Headers 字段,列出实际请求中会包含的自定义请求头。

  2. 服务器接收预检请求:服务器接收到预检请求后,根据自身的 CORS 配置,检查 Origin 以及 Access - Control - Request - MethodAccess - Control - Request - Headers 字段,判断是否允许该请求。

  3. 服务器响应预检请求:如果允许,服务器会在响应头中添加 Access - Control - Allow - Origin 字段,指定允许的源。同时,还会添加 Access - Control - Allow - Methods 字段,列出允许的请求方法;Access - Control - Allow - Headers 字段,列出允许的请求头。此外,还可能有 Access - Control - Max - Age 字段,指定预检请求的结果可以被缓存的时长(以秒为单位)。

  4. 客户端处理预检响应:浏览器接收到预检响应后,检查 CORS 相关头信息。如果预检请求被允许,浏览器会继续发起实际的请求。

  5. 发起实际请求:客户端按照正常流程发起实际的跨域请求,方法和请求头与预检请求中声明的一致。

  6. 服务器接收和响应实际请求:服务器接收实际请求,处理并返回响应,响应头中同样会包含 Access - Control - Allow - Origin 等 CORS 相关头信息,客户端根据这些头信息来决定是否处理响应数据。

在整个过程中,CORS 机制通过请求头和响应头的交互,让服务器能够明确告知浏览器哪些跨域请求是被允许的,从而实现了在遵循同源策略的基础上,安全地进行跨域资源访问。

怎么用CORS实现跨域

以下是使用 CORS(跨域资源共享) 实现跨域的完整方案,涵盖服务端配置、前端请求细节及常见问题处理:


一、CORS 核心机制

CORS 通过服务端设置 HTTP 响应头,告知浏览器允许特定页面的跨域请求。浏览器根据响应头决定是否放行跨域请求。


二、服务端配置

1. 基础响应头设置

在服务端响应中添加以下头信息(以 Node.js 为例):

// Express 中间件示例
app.use((req, res, next) => {
  // 允许的源(根据需求替换为具体域名)
  res.setHeader('Access-Control-Allow-Origin', 'https://your-frontend.com');
  
  // 允许的请求方法
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  
  // 允许的请求头(需明确列出)
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  
  // 允许携带 Cookie(如需)
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  
  // 预检请求缓存时间(秒)
  res.setHeader('Access-Control-Max-Age', '86400');
  
  next();
});

2. 处理预检请求(OPTIONS)

对于非简单请求(如 Content-Type: application/json),浏览器会先发送 OPTIONS 预检请求:

// 单独处理 OPTIONS 请求
app.options('*', (req, res) => {
  res.sendStatus(200);
});

三、前端请求配置

1. 简单请求(Simple Request)

满足以下条件时,浏览器直接发送请求:

  • 方法为 GET/POST/HEAD
  • 头信息仅含AcceptAccept-LanguageContent-LanguageContent-Type(值限于 text/plainmultipart/form-dataapplication/x-www-form-urlencoded

示例

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data));

2. 复杂请求(需预检)

对于其他请求(如 PUT、自定义头、Content-Type: application/json):

fetch('https://api.example.com/data', {
  method: 'PUT',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer xxx'
  },
  body: JSON.stringify({ key: 'value' })
});

3. 携带 Cookie

需前后端协同设置:

// 前端请求添加 credentials
fetch('https://api.example.com/data', {
  credentials: 'include' // 或 'same-origin'
});

// 服务端设置
res.setHeader('Access-Control-Allow-Credentials', 'true');
// 注意:此时 Access-Control-Allow-Origin 不能为 *

五、常见问题与调试

1. 错误排查

  • 预检失败:检查 OPTIONS 响应头是否完整
  • 头信息不匹配:确保 Access-Control-Allow-Headers 包含所有请求头
  • Cookie 未携带:检查前端 credentials 设置和服务端 Allow-Credentials

2. 浏览器控制台警告

  • No 'Access-Control-Allow-Origin' header:服务端未正确设置允许的源
  • Credentials not supported:服务端使用 Access-Control-Allow-Origin: * 但前端尝试携带 Cookie

3. 工具验证

使用 curl 检查响应头:

curl -I -X OPTIONS https://api.example.com/data
# 检查返回的 CORS 头信息

六、安全最佳实践

  1. 限制允许的源:避免使用 Access-Control-Allow-Origin: *,应指定具体域名
  2. 缩小方法范围:按需设置 Access-Control-Allow-Methods
  3. 验证请求头:明确列出允许的请求头(避免使用 *
  4. 限制缓存时间:合理设置 Access-Control-Max-Age(避免过长)

通过以上配置,CORS 可安全高效地实现跨域请求,是现代 Web 应用的首选方案。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 我好像给了友谊一个错误的定义,我总是因为我的好朋友有了新朋友而不高兴。 我的好朋友有了新的圈子新的...
    程cccccccyt啊阅读 461评论 0 0
  • 昨天不是一班的一个男生和我们班的一个女生谈恋爱吗,今天早上那个男生被他们班的老师叫进去办公室了 ,他们老师对他说,...
    开心每一天Wjr阅读 188评论 0 1
  • 和女生沟通时的几副牌: 示弱感情牌、理解共情牌、呵护关心牌、赞美夸奖牌。 一、尤其要不吝赞美(尤其是女生)赞美什么...
    煮雪烹茶惠阅读 172评论 1 1
  • 这天我们班的一个小女生带来了“医药箱”,她一拿过来我们班的小朋友们就非常感兴趣,因为是新来的材料,所以当她...
    XK_4a6b阅读 220评论 0 0
  • 音乐里的故事6 大海 从那遥远海边 慢慢消失的你 本来模糊的脸 竟然渐渐清晰 想要说些什么 又不知从何说起 只有...
    彭求实阅读 339评论 0 2