关于跨域cookie的问题

还原bug情景

昨天组长给我说下,让我改下XX项目的登录接口调用的api,由调用A改成调用B(A,B无任何关系,是2个独立的域名)当时也没多想,以为很简单,就一口答应了。
事实证明,接口调用改造确实很简单,按照新的(B)接口调用要求改了调用的地址和传参的形式,在本地测试一下,没有问题,登录成功,高兴不到一秒后,页面提示“令牌过期”,然后返回了首页,并且是未登录状态。看了下浏览器的network ,登录后的查询首页列表的信息失败了,显示401。

bug追踪

(1)先去查了下401的错误码含义

客户端发送的 HTTP 数据流是正确的,但进入网址 (URL) 资源 , 需要用户身份验证 , 而相关信息 1 )尚未被提供, 或 2 )已提供但没有通过授权测试。这就是通常所知的“ HTTP 基本验证 ”。 需客户端提供的验证请求在 HTTP 协议中被定义为 WWW – 验证标头字段 (WWW-Authenticate header field)

我看了下自己的调用,在heander参数里传了token,那为何授权失败呢,需要进一步查找原因。

(2)看看线上版本正确运行的是如何传参。

从截图圈出来的部分发现还传递了cookie?怎么传递的呢?

于是去红宝书里查了下关于cookie的知识:

关于cookie的说明:

HTTP Cookie,通常直接叫做 cookie, 最初是在客户端 用于存储会话信息的。该标准要求服务器对任意HTTP请求发送Set-Cookie HTTP作为响应头的一部分,其中包含会话信息。

既然是没有传递cookie,那直接给请求设置cookie不久解决了嘛,就类似于设置请求头setRequestHeader那样,可以目前没有这样的api,为什么呢,来自于cookie的限制,cookie在性质上是绑定在特定的域名下的。当设定了一个cookie后,再给创建它的域名发送请求时,都会包含这个cookie。如果没有明确指定,那么这个域会被认作来自设置cookie的那个域。这个限制确保了存储在cookie中的信息只能让批准的接受者访问,而无法被其它域访问。(仔细想想也是,比如你开发了个系统,调用了个第三方服务,你会把重要的信息给它嘛,比如银行卡信息,即使是被加密过的。。。)

扫描二维码关注公众号,回复: 2779012 查看本文章

解决方案

回到我们的bug上,有一种可以尝试的解决方案就是:

(1)在设置cookie时手动设置域名。

var mcookie = {};
//设置cookie
mcookie.setCookie = function(name, value) {
  var Days = 30;
  var exp = new Date();
  exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
  //expires=" + exp.toGMTString() +
  document.cookie = name + "=" + $1.DES.encrypt(value) + ";path=/;domain={A的域名}";
};

在设置cookie时指定域名,我在本地测试了下,发现在获取应用列表时需要的用户信息是空的,没有从cookie里获取到用户信息(难道客户端读的时候也有限制??),我本地的域名是localhost,在网上搜索了下看到

总而言之如果使用COOKIE设置域名尽量少用localhost 或者使用localhost使用火狐,当然如果你不设置域名的话可以正常使用。

我用的谷歌浏览器,改成火狐,还是没有获取到值。手动写了个仿真的用户信息,看看能不能把cookie传给A,结果是空的。

那什么情况可以用这个设置呢,最后在红宝书里看大的答案是子域可以用父域的,举个例子,就是百度图片http://image.baidu.com可以用父域www.baidu.com的cookie信息。

所以可以得出的结论是cookie的作用域是domain本身以及domain下的所有子域名。

所以解决方案一由于浏览器的对cookie的限制而失败。

(2)解决方案
把用cookie传值的请求改为用其它形式的,这样的改动比较大,前后端都要改,但由于第一种探索无效,又不得不改,所以就这种喽~~,代码涉及具体的业务,参考价值不太,就不上了。

猜你喜欢

转载自www.cnblogs.com/JessicaIsEvolving/p/9482775.html