跨域请求如何设置cookie的问题

一、问题背景

  跨域种cookie的问题就是,比如a.123.com跨域访问b.123.com/request,b.123.com服务器使用nginx允许跨域,Access-Control-Allow-Origin:*

  如果a、b服务不在同一个服务器,前台页面请求报错信息为:

Access to XMLHttpRequest at 'http://b.123.com' 
from origin 'http://a.123.com' has been blocked by CORS policy: 
The value of the 'Access-Control-Allow-Origin' header in the response 
must not be the wildcard '*' when the request's credentials mode is 'include'. 
The credentials mode of requests initiated by the XMLHttpRequest 
is controlled by the withCredentials attribute.

  对应ajax请求为:

$.ajax({
  url : 'http://b.123.com/request',
  data : data,
  dataType: 'json',
  type : 'POST',
  xhrFields: {
    withCredentials: true
  },
  crossDomain: true,
  ...

  此时,应取消nginx设置的跨域*,改成代码端设置。且代码服务器端通过在响应 header 中设置

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

  来运行客户端携带证书式访问。通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie。

  服务器端 Access-Control-Allow-Credentials = true时,Access-Control-Allow-Origin 的值不能为 '*' ,应设置为发起请求的地址。

// a.com发来的请求
response.setHeader("Access-Control-Allow-Origin", a.123.com);

  b服务器在设置cookie时,需设置

cookie.setPath("/");
cookie.setDomain("123.com");

  否则设置的cookie无法生效。

二、跨域请求怎么携带cookie呢?

  解决跨域携带cookie问题

1、在前端请求的时候设置request对象的属性withCredentials为true

  什么是withCredentialsXMLHttpRequest.withCredentials 属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用withCredentials属性是无效的。

  如果在发送来自其他域的XMLHttpRequest请求之前,未设置withCredentials 为true,那么就不能为它自己的域设置cookie值。而通过设置withCredentials 为true获得的第三方cookies,将会依旧享受同源策略,因此不能被通过document.cookie或者从头部相应请求的脚本等访问。

// 修改跨域请求的代码
crossButton.onclick = function () {
    axios({
      withCredentials: true, // ++ 新增
      method: "get",
      url: "http://localhost:8003/anotherService",
    }).then((res) => {
      console.log(res);
    });
};

  这个时候再去发送一个跨域请求,你会发现依旧报错,但是我们仔细看下报错,意思是需要设置header的Access-Control-Allow-Origin属性:

2、在服务端设置Access-Control-Allow-Origin

  这个就是上面问题背景的问题

// 在所有路由前增加,可以拦截所有请求
app.all("*", (req, res, next) => {
  res.header("Access-Control-Allow-Origin", "http://localhost:8000");
  next();
});

  但是还是会报错:修改完之后再次发送一个跨域请求,你会发现,又报错了,但是跟之前报的错不一样了,意思大概就是Access-Control-Allow-Credentials这个属性应该设置为true,但是显示得到的是个''

3、在服务端设置Access-Control-Allow-Credentials

// 在所有路由前增加,可以拦截所有请求
app.all("*", (req, res, next) => {
  res.header("Access-Control-Allow-Origin", "http://localhost:8000");
  res.header("Access-Control-Allow-Credentials", "true"); // ++ 新增
  next();
});

  这样即可成功。

posted @ 2017-10-19 23:46  古兰精  阅读(3803)  评论(0编辑  收藏  举报