在开始之前我就在 login.taobao.com 登陆了自己的淘宝账户

之后打开 tmall

淘宝将认证 token 存放在 taobao.com 域名下

tmall 想要得到 taobao.com cookies 必然涉及到跨域

两个对于 taobao.com 的域名的访问全部使用了 jsonp

第一个 login_api 获取了 taobao.com 域名下的 cookies
以 名为 userCookieJSObject 返回
并回调了 TB.Global.run()


Chrome 对于跨域请求隐藏了 Request Headers,这里显示 Provisional headers are shown

但同一个请求,在 Firefox 上可以完全显示

我当时卡在这里很长时间,因为发现 browser 没有发送 cookies 就收到了 server 回复的 taobao cookies,肯定遗漏了什么

结果看到
https://www.chromium.org/Home/chromium-security/site-isolation#TOC-Known-Issues

In Chrome’s DevTools, cookies and other request headers are not shown in the network panel for cross-site subresource requests. There are also issues with the DOM storage view, security panel, performance panel, and with scrolling over cross-site iframes in mobile device emulation mode, all of which are fixed in Chrome 68.

说是 Chrome 68 就修复了,但我 72 版本还是有这个问题
。先扔这


下面换 Firefox 看请求

TB这个obj绑定了许多方法,可以看下

key的 value 已全部删除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var userCookie = {
dnk: '',
_nk_: '',
_l_g_: '',
ck1: '',
tracknick: '',
mt: '',
l: '',
uc1: '',
t: '',
unb: '',
cna: '',
_tb_token_: '',
version: ''
};
window.TB && TB.Global && TB.Global.run && TB.Global.run();

比较奇怪的是 run 是个空函数,什么都不做,不知道 run 存在的意义是什么

1
run: function() {}


获取到 usercookie 之后并非什么都不做,事实上整个请求被包裹进了回调,真正的login过程在下面的钩子函数中

先看下堆栈

这是初始化流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
_initLoginStatus: function() {
var e = o.Global;
var a = o.userInfo;
var t = i.Cookie.get("_nk_") || "";
t = H(unescape(t.replace(/\\u/g, "%u")));
var n = i.Cookie.get("_l_g_") || "";
e._seedLoginApi(function() {
o.userInfo.status = "success";
a.nick = H(unescape(userCookie["_nk_"].replace(/\\u/g, "%u")));
a.displayNick = H(unescape((userCookie["dnk"] || userCookie["_nk_"]).replace(/\\u/g, "%u")));
a.tracknick = H(unescape(userCookie["tracknick"].replace(/\\u/g, "%u")));
a.isLogin = !!(userCookie["_l_g_"] && a.nick);
a.trackId = userCookie["t"] || "";
a.unb = userCookie["unb"] || "";
a.uc1 = userCookie["uc1"] || "";
a.cookie2 = userCookie["cookie2"] || "";
a.tbToken = userCookie["_tb_token_"] || "";
var n = i.unparam(a.uc1);
a.isMallSeller = !!n.tmb;
a.tag = n.tag;
if (a.isLogin && (a.nick != t || !a.tbToken)) {
// 因为已经拿到了usercookie,现在开始
// 跳转到 tmall的域名,然后set cookies
var s = "//tmcc.tmall.com/pass.htm";
if (f) {
s = "//tmcc.daily.tmall.net/pass.htm"
}
A(s)
}
e._fireLoginStatusReadyFnList()
}, function() {
o.userInfo.status = "error";
e._fireLoginStatusReadyFnList()
})
},
_seedLoginApi: function(e, a) {
// 确认 login_api 用哪个接口
var t = "//top-tmm.taobao.com/login_api.do";
if (f) {
t = "//www.daily.taobao.net/go/app/tmall/login-api.php"
}
// e 就是上面的回调function
// success 字面推断成功之后回调e
// 淘宝使用了一个 kissy 的库
// https://docs.kissyui.com/1.1.6/ajax/index.html#method_getScript
t += "?" + Math.random();
i.getScript(t, {
success: e,
error: a,
timeout: 3
})
},

然后到了第二个 jsonp 跨域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
_initMemberInfoCallback({
"activeStatus": -1,
"availablePoints": 789,
"cookies": {
"uc1": {
"value": "so many cookies"
},
"t": {
"value": "so many cookies"
},
"unb": {
"value": "so many cookies"
}
},
"expiredPoints": 0,
"lastMessage": "",
"lastMessageId": 0,
"lastMessageType": 0,
"lastMessageUrl": "//vip.tmall.com/messagebox/index.htm",
"login": true,
"mallSeller": false,
"messagePopup": true,
"newMessage": 0,
"newMsgList": {
"1": 0,
"2": 0,
"3": 0
},
"taskId": ""
});

这里回调了新的 _initMemberInfoCallback 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
m._initMemberInfoCallback = function(t) {
a.memberInfo = t;
a.memberInfo.cookies = {
unb: {
value: a.unb
},
t: {
value: a.t
},
uc1: {
value: a.uc1
},
login: true
};
a.memberInfo.mallSeller = a.isMallSeller;
a.memberInfo.status = "success";
e._fireMemberInfoReadyFnList()
}

接二连三的 302, 最后以 200 作为跳转的结束

通过 跳转到 pass.tmall.com 来给 .tmall.com域名 设置 cookies,配置免登陆

最后总结一下, taobao.com 登陆之后将 cookies 放到 taobao.com

然后在 tmail.com 利用跨域向 top-tmm.taobao.comcookies 请求,
后台校验成功之后返回 taobao.com 下的 cookies ,这样我们就在

tmall.com 域名下 得到了 taobao.comcookies,下面进行多次 302,最后在 pass.tmall.com 下将 这些 cookies set 上去,由于后台公用鉴权系统,访问 天猫 时我们就已经登陆了

对于 loginout ,其实也差不多,进行多次跳转,每次都将 cookies 发往 阿里的多个域名的 clear 接口