跨站请求如何携带凭证

143 阅读2分钟

站请求怎么成功

跨站请求需要服务端同意,在指定请求响应头中设置Access-Control-Allow-Origin指定该响应允许被哪些域共享。

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>

Access-Control-Allow-Origin设置为我们的域名之后即可成功访问。

如何携带凭据

通过Access-Control-Allow-Origin可以成功跨站访问,但是我们通过debug会发现,请求没有携带cookie,这是因为我们没有在请求中指示是否要使用cookie、authorization、headers或者TLS客户端证书等凭据来创建跨站点访问。可以通过请求的withCredentials属性来开启它。

const xhr = new XMLHtppRequest()
xhr.withCredentials = true
xhr.open('GET', 'http://example.com', true)
xhr.send(null)

我们再刷新请求会发现请求直接报错了,这是因为我们请求指示要求服务器允许使用凭据,但是服务器响应并没有指示允许。这时候还要在响应头中设置Access-Control-Allow-Credentialstrue来明确允许。除此之外Access-Control-Allow-Origin不能是通配符比如*,而是必须是明确的值,就是必须明确允许请求的域

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: <origin>

在旧版的浏览器中,基于上方的配置就能成功在请求中携带cookie了。

新版本,安全性升级

我们基于上访配置在chrome51之后的浏览器访问会发现依旧没有携带上cookie访问,这是因为在chrome51之后浏览器对cookie新增了一个会影响跨站携带凭证的属性 SameSite,下面是这个属性的值:

  • Strict,严格的,完全禁止第三方cookie,只有当前网页URL与请求目标一致才会携带。可能造成不好的用户体验,比如从一个github连接点击进去不会携带cookie会被判断为未登录
  • Lax,稍微宽松,大多数不允许第三方cookie,从导航到目标地址的Get (链接,预加载请求,GET表单) 除外。
  • None允许第三方跨站访问携带cookie,该属性有一个要求,必须同时为cookie设置Secure (该值指明cookie只能在https请求中被携带),第三方必须是https协议的源。

所以除了对新版本中响应的cookie设置为SameSite=None; Secure外,请求放必须是https站点。

Set-Cookie: xxx; SameSite=None; Secure