Node.js - 跨域 cors

599 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情

什么是 cors

cors (Cross-Origin Resource Sharing, 跨域资源共享)由一系列 HTTP 响应头组成,这些 HTTP 响应头决定浏览器是否阻止前端 js 代码跨域获取资源

浏览器的同源安全策略默认会阻止网页 “跨域” 获取资源,但如果接口服务器配置了 cors 相关的 HTTP 响应头,就可以解除浏览器端的跨域访问限制

Snip20220412_9.png


cors 注意事项

  • cors 主要在服务器端进行配置,客户端浏览器无需做任何额外的配置,即可请求开启了 cors 的接口

  • cors 在浏览器中有兼容性,只支持 XMLHttpRequest Level2 的浏览器,才能正常访问开启了 cors 的服务器接口(如 IE10、Chrome4+、Firefox3.5)


cors 响应头(Access-Control-Allow-*)

Access-Control-Allow-Origin

  • 响应头部中可以携带一个 Access-Control-Allow-Origin 字段

    Access-Control-Allow-Origin: <origin> | *
    
  • origin 参数的值指定了允许访问该资源的外域 URL

    示例(只允许来自 studyNode.cn 的请求)

    res.setHeader('Access-Control-Allow-Origin', 'http://studyNode.cn')
    
  • 如果指定了 Access-Control-Allow-Origin 字段的值为通配符 *,表示允许来自任何域的请求

    res.setHeader('Access-Control-Allow-Origin', '*')
    

Access-Control-Allow-Headers

  • 默认情况下,cors 仅支持客户端向服务器发送如下九个请求头

    • Accept
    • Accept-Language
    • Content-Language
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
    • Content-Type(值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)
  • 如果客户端向服务器发送了额外的请求头信息,则需要在服务器端通过 Access-Control-Allow-Headers 对额外的请求头进行声明,否则这次请求失败

    // 允许客户端额外向服务器发送 Content-Type 请求头和 X-Custom-Header 请求头
    
    // 注意:多个请求头之间使用英文的逗号进行分割
    res.setHeader('Access-Control-Allow-Headers','Content-Type,X-Custom-Header')
    

Access-Control-Allow-Methods

  • 默认情况下,cors 仅支持客户端发起 GET、POST、HEAD 请求
  • 如果客户端希望通过 PUT、DELETE 等方式发起请求服务器的资源,则需要在服务器端,通过 Access-Control-Allow-Methods 来指明实际请求所允许使用的 HTTP 方法
// 只允许 POST、GET、DELETE、HEAD 请求方法
res.setHeader('Access-Control-Allow-Methods','POST、GET、DELETE、HEAD')

// 允许所有的 HTTP 请求方法
res.setHeader('Access-Control-Allow-Methods','*')

cors 请求的分类

客户端在请求 cors 接口时,根据请求方式和请求头的不同,可以将 cors 的请求分为俩大类

  • 简单请求
  • 预检请求

简单请求

同事满足俩个条件就属于简单请求

  • 请求方式:GET、POST、HEAD 三者之一

  • HTTP 头部信息不超过以下几种字段,无自定义头部字段

    • Accept
    • Accept-Language
    • Content-Language
    • DPR
    • Downlink
    • Save-Data
    • Viewport-Width
    • Width
    • Content-Type(值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)

预检请求

只要符合以下任何一个条件的请求,都需要进行预检请求

  • 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
  • 请求头中包含自定义头部字段
  • 向服务器发送了 application/json 格式的数据

在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,已获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为预检请求。服务器成功响应预检请求后,才会送到真正的请求,并且携带真是数据

简单请求和预检请求的区别

  • 简单请求的特点:客户端与服务器之间只会发送一次请求
  • 预检请求的特点:客户端与服务器之间会发生俩次请求,OPTION 预检请求成功之后,才会发起真正的请求