这是 Jerry 2021 年的第 50 篇文章,也是汪子熙公众号总共第 327 篇原创文章。
今天文章提到的场景,理论上本公众号每一位粉丝,都可以在自己的电脑上进行操作。因为涉及到的应用,几乎每一个人日常生活中都会使用到——淘宝网。
Jerry 负责的是 SAP Commerce Cloud 前台开发,为何要写和淘宝网相关的文章?
上个周日即7月25日凌晨两点半,Jerry 所在的 Spartacus 开发团队,收到了一个客户 escalation.
这个客户 incident 和会话管理 (Session Management) 相关,因此 Jerry 一边和同事处理问题,一边不禁联想起,作为另一款国内外数一数二的电商网站,淘宝网是如何处理类似问题的?
在电脑端访问淘宝网,输入淘宝用户名和密码,点击登录:
会观察到一个 HTTP Post 请求,login,发送往后台服务器:
https://login.taobao.com/newlogin/login.do?appName=taobao&fromSite=0
该请求的 Form Data 中包含 loginId 和 password2 两个字段,分别维护了用户输入的淘宝用户名的明文,以及淘宝密码进行 RSA 加密后的值。
下面介绍如何自行找到淘宝网前端将用户输入的登录密码进行 RSA 加密的准确位置。
在 Chrome 开发者工具里找到 login 请求,在 Initiator 面板里找到发起该请求的调用栈。稍有经验的前端开发人员,从 onClick 和 t.loginSubmit 就能推断出,用户名和密码的输入框,实现在一个 Form 表单里,点击登录按钮后,触发表单的 Submit.
打开上图找到的 index.js 文件:
https://x.alicdn.com/vip/havana-nlogin/0.5.61/index.js
直接搜索关键字 password2,很快就能找到 RSA 加密的代码位置:
设置断点后,运行时点击登录按钮,断点触发,可以进入 rsaPassword 函数,查看 RSA 加密算法的明细。
这个 index.js 里还能发现一些有趣的东西。比如提供了 rsaPassword 方法的模块内部,还维护了一个支持的国家列表,countryList,里面有 168 个国家和地区:
但是在浏览器端打开淘宝网,国家和地区的下拉列表里,只能看到十余条记录。这应该是前台某处根据某种逻辑做了过滤:
此外,我们在淘宝网首页右边区域,能看到快速充值话费的面板,如下图绿色高亮区域所示:
该页面的 HTML 源代码,并不是静态编写于首页的 HTML 文件中,而是通过一个叫做 bianming-phone("便民"的拼音加上"手机"的英文单词 phone,这混搭风格......) 的 HTTP 请求,从后台读取到前台,然后再注入到前台页面中:
同理,还有这个旅行视图片段(相当于 SAP UI5 里的 View Fragment):
读取该视图片段的 HTTP 请求:bianming-trip
看到这里,Jerry 不由得联想起 SAP Commerce Cloud 前台的 CMS 驱动设计,二者都是从电商页面连接的后台系统读取部分页面配置信息,可谓异曲同工。
SAP S/4HANA 的 UI 风格是 Fiori UX,实现的前端框架是 SAP UI5;SAP Commerce Cloud UI 实现的前端框架是 Angular;
help.sap.com 采用 AngulaJS 实现,www.sap.com 使用的是 React.详情参考 Jerry 的文章:SAP官方帮助网站,help.sap.com 背后那些事儿。
而淘宝网首页,采用的是阿里自研的前端框架,Kissy:
我们在淘宝网首页看到琳琅满目的商品图片,都是被 Kissy 驱动,通过向 CDN 服务器发起的数据请求而被加载的:
在这些页面片段的源代码里还看到一些有意思的内容,比如这种“上线请删除”的注释。我现在浏览的就是上线后的代码呀,咋还能够看到这些注释 :)
还有这种给 window 全局对象添加 flag 属性,赋值为 5 的做法。作为同行,我非常能理解这种 workaround :)
想起有一段在国外程序员界很流行的注释,翻译成中文大意是:
// 下面这段代码不要动,因为只有我和上帝,知道这段代码在干啥
// 现在,只有上帝知道这段代码在干啥
我们在淘宝网上购物时,选择好了自己心仪的商品,加入购物车之后,当然不希望点击结帐之后,忽然弹出要求重新登录的界面,这岂不是令人扫兴。另外,当我们不小心误操作,点击了浏览器刷新按钮,我们期望页面刷新后,仍然处于登录状态,之前添加到购物车里的商品不会丢失。这些都属于用户会话管理的范畴。
淘宝网页面的用户会话管理,是通过客户端 Cookie 和服务器端维护的用户会话对象来实现的。
用户成功登录淘宝网之后,服务器创建对应的 Session 对象,返回给 login HTTP 请求的响应头部,包含了很多 set-cookie 字段:
浏览器解析这些响应,将服务器颁发的 Cookie 设置到本地。下一次用户操作淘宝网,触发新的发向服务器端的请求时,浏览器会自动将这些 Cookie 字段设置到请求头部。服务器接收到这些 Cookie 字段,就能在内存中定位到之前该用户登录后对应创建的 Session 对象,从而能够识别出该用户。
这些 Cookie 在 Chrome 开发者工具里也能查看。
(1) Cookie 的 Expires 字段存放的是过期时间,当 Expires 为 Session 时,意为该 Cookie 只在当前会话内有效,浏览器关闭则 Cookie 自动删除。
(2) 带有 Http Only 的 Cookie,无法被客户端 JavaScript 代码读取,提高了安全性,避免了 Cookie 通过 XSS 攻击被窃取的可能。
(3) Secure 为 true 的 Cookie,无法通过 HTTP 协议传输到服务器,只能通过 HTTPS 发送。
淘宝服务器颁发的 Cookie 里,字段 lid 存储的是淘宝用户名经过 URL encode 之后的值,dnk 存放的是淘宝用户名的 Unicode:
有了本文的基础,下一篇文章 Jerry 会介绍 SAP Commerce Cloud UI 的用户会话管理,感谢阅读。
联系客服