[版权声明] 本站内容采用 知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆 (CC BY-NC-SA 3.0 CN) 进行许可。
部分内容和资源来自网络,纯学习研究使用。如有侵犯您的权益,请及时联系我,我将尽快处理。
如转载请注明来自: Broly的博客,本文链接: 扫二维码登录微信网页版原理分析
出于项目要求,需要制作一个扫描二维码登录网页后台的功能。所以研究了下微信网页版的扫二维码登录功能,希望能有所借鉴和收获。
首先我们先来熟悉一下整个扫二维码登录的流程:
- 打开微信网页版
- 打开微信客户端APP
- 扫网页上的二维码(扫一扫)授权登录
- 登录成功并跳转
原理分析:
打开微信网页版的登录页面,按F12打开Chrome调试模式。
我们可以看到,网页先后加载了网页、图片、CSS、Javascript等资源文件,包括二维码图片。
然后仔细观察会发现,网页会一直在异步请求一个链接,这个链接其实就是在监听服务器,如果有人用微信客户端授权成功,则会返回成功的信息然后跳转;否则继续监听。
这个过程就是整个网页最重要的部分了,通过不断请求来监听状态。所以需要重点分析此请求。
从图中我们还可以看到,右侧,每个请求都是用了27s左右。为什么要这么长时间呢?
由于监听和登录操作肯定是短时间内必须完成的,比如我扫完二维码确认登录了,这个页面就要在短时间内做出响应。如果要做到这样,最简单的方法就是通过Javascript定时器,每隔几秒请求服务器并获取状态(事实上我同时也研究过新浪微博的扫二维码登录,它就是这样做的,每隔3-4秒左右请求一次)。然而这样会直接导致的问题就是,服务器会产生非常高的并发,小用户级别的服务器还没什么,但是像微信这种需要服务庞大用户群的服务器,就必须做这方面的优化。
所以微信的采用的做法就是减少请求并增加响应时间,实现的原理大概就是在服务器端接收到请求后,内部加个定时器不断检查用户授权的状态,如果检测到用户授权则马上响应给网页端;否则继续检查;当时间累积到27秒左右,不论成不成功都终止检测并立即响应给网页端。
好了,我们接下来继续观察这个请求的参数:
可以看到总共有五个参数:
loginicon :布尔值
uuid:字符串
tip :正整数
r:负整数
_:正整数
从字面上来理解的话,第一个参数大概意思是,是否要有登录图标(true=>要,false=>不要);第二个参数,是指二维码的值,随便测试下就知道了;第三个参数,应该是指是否要提示(1=>要,0=>不要);第四个参数,应该是一个随机数(random);第五个参数,不难看出这是个Unix时间戳。随机数和时间戳跟安全机制有关吧,防止相关的攻击,如重放攻击。
这几个参数当中,最重要的是当然是uuid了,因为这是用来向服务器请求授权状态的凭借。并且这个uuid必须是唯一不重复的,不然试想下,两个人在不同的电脑下浏览到了同一个二维码,有人授权登录了,可能会是在另一个人电脑上登录微信的网页版。所以说这个唯一的uuid是专门用来绑定一个微信账号的授权的。
因为uuid一般是随机生成的,但是像这里的这串字符,观察最后两个字符“==”,又像是经过某个加密算法产生的,不过这并不太重要,确保到uuid的唯一不重复性就行了。至于r这个参数,我个人猜测这是个随机数。最后一个参数是用来做超时验证操作的,确保一个uuid只在短时间内有效,如果你仔细观察,会发现二维码登录页在几分钟内不登录,那么它会自动刷新然后更新过另外一个二维码。最后利用这三个进行某种算法之后生成签名(下面提到的ticket值)返回给客户端。
接下来我们看看这个请求的返回值:
从图中我们可以看到返回的是一条Javascript语句,有个状态码408,这个就是表示用户还没有用微信客户端APP授权,需要继续请求监听状态。如果是授权成功,则返回200,然后登录页会跳转到后台:
1 2 |
window.code=200; window.redirect_uri="https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=A1aIfKKbwSFQF62r2rlGJoMP@qrticket_0&uuid=gfYCj6pglQ==&lang=zh_CN&scan=1456813161"; |
ticket值就是服务器生成的用户签名,理解为access_token即可。
再来看看微信客户端APP扫描二维码后的页面:
当扫描成功二维码后,会弹出授权窗口,询问是否授权登录。
换个二维码扫描软件可以得到登录时候的二维码字符串实际值如图。经过多次试验可以知道前半段不变的,只有后面的参数会变(即uuid值)。
所以分析得到微信客户端的步骤是这样的:
- 扫描二维码(扫一扫)
- 如果字符串前半段是https://login.weixin.qq.com/l/,则弹出授权窗口
- 如果点击确定,再向服务器请求改变这个uuid的状态
完整的流程图:
至此,整个的扫二维码登录流程就完成了。
有两个==是base64的吧