ajax跨域请求携带cookie

9,109 阅读2分钟

    因为浏览器的同源策略的限制,不同域名间的请求会造成跨域问题(同源策略是客户端的限制,服务端的互相请求不会有跨域问题)。一般场景下解决跨域问题常用的解决方法都是CORS解决,即配置服务端接受发起请求的域名

 response.header('Access-Control-Allow-Origin', '*'); // *表示支持所有的域名,可以换成具体的域名

    现在ajax的请求可以得到返回值了,但是默认跨域请求是不携带cookie的,如果碰到一些需求必须从cookie中取值,分两种情况

  1. 一级域名相同.二级域名不相同,且cookie在一级域名下,可以设置
 document.domain = '一级域名'

就可以携带cookie了。

2.一级域名不同,可以配置XMLHttpRequest.withCredentials 来允许ajax请求时携带cookie。

/* jQuery支持跨域携带cookie */
$.ajax({
    type:'get',
    crossDomain:true, //设置跨域为true
    xhrFields: {
        withCredentials: true //默认情况下,标准的跨域请求是不会发送cookie的
    },
}})
/* 原生ajax支持 */
var xhr = new XMLHttpRequest()
 xhr.open("GET",url,true);
 xhr.withCredentials = true;
 xhr.send(null);
 xhr.onreadystatechange = function () {
  if(xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
    console.log(xhr.responseText)
  }
}
/* axios支持 */
axios.defaults.withCredentials = true

    同时服务器server端要配置Access-Control-Allow-Credentials,我们在客户端设置了withCredentials=true 参数,对应着服务器端要通过在响应 header 中设置Access-Control-Allow-Credentials = true来运行客户端携带证书式的访问。通过对Credentials参数的设置,就可以保持跨域Ajax时传递的Cookie。

response.setHeader("Access-Control-Allow-Credentials", "true");

    服务器server端要配置Access-Control-Allow-Origin到以上配置为止,发送ajax请求,我们发现还会出现一个错误,提示我们 Access-Control-Allow-Origin 不能用 * 通配符。原因是:当服务器端 Access-Control-Allow-Credentials = true时,参数Access-Control-Allow-Origin 的值不能为 '*' 。我们重新设置Access-Control-Allow-Origin的值,当服务器端接收到请求后,在返回响应时,把请求的域Origin填写到响应的Header信息里(即谁访问我,我允许谁),代码如下:

response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

最后补充一点ajax的post请求Content-Type,但仅能是下列之一

    application/x-www-form-urlencoded
    multipart/form-data
    text/plain

不然可能就会报以下的错误

XMLHttpRequest cannot load www.mydomain.com/?/ac... No 'Access-Control-Allow-Origin' header is present on the www.mydomain.com/?/ac... requested resource. Origin 'www.mydomain.com' is therefore not allowed access.

最后附上cors请求流程图

ps:以上内容参考了很多网友的答案,再此表示感谢。

注意

谷歌浏览器从版本84,火狐浏览器从版本69默认的sameSite将变为lax,网站可以选择显式关闭SameSite属性,将其设为None。不过,前提是必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

下面的设置无效。

Set-Cookie: widget_session=abc123; SameSite=None

下面的设置有效。

Set-Cookie: widget_session=abc123; SameSite=None; Secure

参考资料 web.dev/samesite-co…