前言

跨域必须掌握。

这个算是个比较低级的应用场景了,只是之前一直没有遇到,最常见的应用场景应该是:

  1. 用户登录,获得登录态,存在 cookie 中
  2. 用户交互时发起 Ajax 请求,这时需要带上 cookie,让后台知道这个请求是哪个用户发过来的

大家平时应该会有这么个不太准确的认识:
>
ajax 请求默认不带 cookie,要是想让它带上,则必须要设置其 XMLHttpRequest 实例的属性 withCredentialstrue

只能说以上的表述是不准确的,完整无歧义的表述如下:

  1. 同源异步请求时,ajax 会默认自动带上 cookie
  2. 跨域异步请求时,ajax 默认不会带上 cookie
  3. 可以通过前端设置 XMLHttpRequest 实例属性 withCredentialstrue,且后端设置 Headers 的方式来让 ajax 自动带上不同源的 cookie;但该属性对同源请求没有任何影响,会被自动忽略

所以,关键点就在 withCredentials 属性了。

前端实现

接下来说说在不同的库内,如何实现带 cookie。

原生 XMLHttpRquest

这个就比较简单了,直接参考 MDN 上的 XMLHttpRequest.withCredentials

1
2
3
4
5
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/', true);
// Pay attention
xhr.withCredentials = true;
xhr.send(null);

jQuery/Zepto 实现

针对 $.ajax() 方法传入配置如下:

1
2
3
4
5
6
7
8
9
const ajaxSettings = {
type: 'POST',
timeout: 25000,
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
dataType: 'json',
xhrFields: { withCredentials: true },
crossDomain: true,
// ...
}

配置属性解释:

  • crossDomain: true: 启用 ajax 跨域功能
  • xhrFields: { withCredentials: true },: 启用 ajax 在跨域时带上 cookie

axios 实现

1
2
3
4
5
6
7
8
axios.request(config = {
baseURL: 'https://api.example.com/'
url: '/example',
method: 'get',
headers: {'X-Requested-With': 'XMLHttpRequest'},
withCredentials: true
// withCredentials: false, // default
});

服务端配合

用 php 来举例:

1
2
3
4
5
<?php
header("Access-Control-Allow-Origin: http://example.com");
header('Access-Control-Allow-Credentials:true');
// ...
?>

要非常注意的一点就是:

  • 服务器端 Access-Control-Allow-Credentials = true 时,参数 Access-Control-Allow-Origin 的值不能为 '*'

参考链接