微信扫描二维码登录网页是什么原理,前后两个事件是如何联系的?(转)

本贴最后更新于 1956 天前,其中的信息可能已经渤澥桑田
黄良懿,做做架构,写写代码
反对 @朱立雄 的答案,从回答可以看得出来他对技术细节并不了解。对前端开发有了解的同学随便开个 Firebug 看看登录过程的 Net 视图基本就能大概看清楚这个过程。
我个人开发过程一般是和产品说,『你们提业务要求、交互方式、性能要求等就好,技术方案我们会综合开发时间、系统架构等因素考虑』。
恰好我之前也花过几个小时做过类似的验证登录过程,这里作为探讨,把产品同学的回答做个引用,解释一下其中『不技术』的地方。

1. 每打开一次微信网页版页面的时候会随机生成一个含有唯一uid的二维码,每次刷新页面都会不一样(这个可以保证一个uid只可以绑定一个账号和密码,如果一个uid可以绑定多个账号和密码,那么很可能你的电脑会登陆别人的微信哦);
确实返回了唯一 id,但目的是为了识别用户身份,而且实际上打开这个页面的时候浏览器已经和 Server 创建了一个长连接等待确认信息。
查看 http://wx.qq.com 的源码可以看到,这个页面在加载完毕时,也已经把很多登录后才需要的相关资源都预先加载进来了,所以长连接等待登录用户得到确认后展示用户信息的速度很快,因为无需刷页面和加载头像外的其他资源。

2. 当用户使用登陆后的微信扫描该二维码的时候,会将这个id和手机上的微信账号及密码绑定,并上传到微信网页版服务器;
先上个图:

二维码样例: http://weixin.qq.com/x/ARmFYVvUzczwBl9u6Y1I ,利用我查查之类的二维码应用可以得到类似这样的地址,但并不会自动打开该地址,微信客户端针对 http://weixin.qq.com/x/ 开头的地址做了特殊处理,会自动获取相关信息并提示确认。 在手机版微信访问这个页面进行确认时,Server已经同时获得了客户端信息,并通过之前保持的长连接告知浏览器。

3. 微信网页版页面每隔1秒或2秒会get请求该id对应的微信账号及密码,如果id绑定上了微信账号和密码,那么就可以请求到账号和密码,就可以自动登陆了。
浏览器展示完长连接里包含的用户信息(头像等)后,会新开一个长连接等待客户端的确认操作,其 URL 类似 https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?uuid=794ecedd804f47&tip=1&_=1395748413642 。从安全的角度来说,无论如何都不会让客户端获得微信帐号和密码的。要知道,密码这玩意腾讯自己都不敢保存(有兴趣的同学可以自行了解下 CSDN 明文密码泄露事件),肯定是不可能返回给浏览器的。
而且从体感来看,怎么着都不可能是页面1-2秒轮询发起GET请求的,实际是通过堵塞等待的长连接,近乎实时的获得信息。 对于验证过程,Open API 一般是通过授权令牌(Token)来解决的,原理是当用户通过授权后,分配一个限定条件下的令牌(如限制本机访问、限制授权有效时间、限制同时登录设备数等),使获得授权的用户仅在有限的前提下能访问相关服务。 像计算机休眠后曾做的授权就自动收回了,这样就有效的避免了在别人电脑上(尤其是网吧)打开,但忘记关闭或退出这类安全问题了。
同时,整个授权过程的验证部分在手机端进行,有效杜绝了 PC 上泛滥的各类木马、『安全工具』的监听,大大降低了帐号被盗的风险。

所以说,核心过程应该是:浏览器获得一个临时 id,通过长连接等待客户端扫描带有此 id 的二维码后,从长连接中获得客户端上报给 server 的帐号信息进行展示。 并在客户端点击确认后,获得服务器授信的令牌,进行随后的信息交互过程。 在超时、网络断开、其他设备上登录后,此前获得的令牌或丢失、或失效,对授权过程形成有效的安全防护。
编辑于 2014-03-26 30 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
30赞同反对,不会显示你的姓名
吕十田,我想说你们都在胡说八道可以么?
李胜龙知乎用户、曹胜奇 
诸多先贤告诉我们,不要挑起事端。
诸多先贤还告诉我们,要说人话。
签名表明了我的态度,那我就简单说几句,喂,就几句,不要抢我的稿子!

1、你用浏览器打开http://wx.qq.com的时候,微信给你随机分配了一个链接,【相当于给你开了间房,房号1024,注意,只给你房号,没给你钥匙】,用二维码包装着,并且设置了有效时间【10分钟你不进房间,就给你取消】。这里面没有用户什么事情,所以不存在UID(user ID),只是一个随机的字母和数字组合。
2、二维码的转码规则是统一的,所以意味着,只要是个二维码扫描软件,谁都能拿到这个链接,微信可以扫出来,我查查也可以扫出来。
3、所以拿到链接没有用,重要的是谁拿到链接,微信拿到了,就可以从微信客户端发一条信息给服务器,告诉服务器,现在是谁使用了某个链接,其他二维码扫描软件,不能和微信服务器通话,所以毫无价值。【你拿到了房号,就给酒店老板打个电话,说是我,老板就知道张三又来开房了,其他人没有老板电话,知道房号也没用】
4、这时候,在你刚打开的浏览器窗口里面,就知道并显示了你的信息,理论上可以直接打开聊天窗口,但是为了不突兀不尴尬,微信选择再让你在手机上做一个确认操作。【你站到你的房间门口了,老板也知道你是张三了,并且把你的那个好基友也放到了你房间里,但是谁知道你基友会在房间里干点啥?如果他正好弯腰在捡肥皂,这时候恰好你后面有人经过,房门大开大家尴尬不尴尬?所以还是老板考虑周到,他要你在电话里确认一下才给你开门,你大可以等后面没人了再开门进去】
5、好了,现在你可以进去好好享用你的基友了。
发布于 2014-03-27 9 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
3赞同反对,不会显示你的姓名
知乎用户,饭妈妈/咕咕监控/我的心愿
nero lou施宏墨婉 赞同
使用Fiddler抓包就可以看到了啊。
Web页面保持长连接,微信点击登录后POST数据,Web页面捕获到进行加载用户列表等功能。
就这么个流程啊。
发布于 2014-03-25 1 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
28赞同反对,不会显示你的姓名
谢然,没有抗争就没有自由
有人对这个存在疑问是因为,扫码登陆有那么一点点违背直觉。
违背直觉的地方在于,电脑端是如何知道是哪个微信账号扫的它?
传统的登陆方法都是我告诉(输入)登陆设备我的账号密码等信息,然后就登陆了。
而这个是反过来的,微信扫码,信息(二维码)是从被登陆设备(电脑)往手机(微信)传的,违背直觉的地方就在这里。信息传递的方向是反的。

然而多想一步就会明白,不管是手机还是网页端,都是和微信的服务器连接的。
微信在扫到码后告诉微信的服务器它扫到的是哪一个码。
服务器知道当前这个码是在哪一个网页上显示的,于是这两者就联系起来了。

举个例子,比如你在街上看到一个美女,你不知道她的名字等联系方式,但你牢牢的记住了她的长像。然后你跑到公安局里去通过她的长相查到了她本人,公安局联系她本人说有个人要找她,最终你们取得了联系。这里公安局就是微信的服务器,你就是微信,她就是网页端。比喻不太恰当,凑合一下吧~

值得注意的是这个过程中没有用户名密码等的验证。
因为这是基于一个信任来登陆的:即服务器相信能用微信扫码的话,扫码人就拥有这个微信账号的所有权。微信在首屏也提供了从手机上退出网页登陆的功能,这样即使是别人拿着你的手机扫了码在他的电脑上登陆你的微信,你也可以发现。
整个过程是没有逻辑漏洞的。
编辑于 2014-03-29 6 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
3赞同反对,不会显示你的姓名
walker,用户
Joson Jiang陈骏知乎用户 赞同
微信和airdroid都有扫描二维码登录的功能,实现略有差别。
如果你用普通的二维码扫描工具扫描它们的二维码,微信得到一个网址,airdroid得到一个字符串,但是里面都会有一个唯一的ID,这一点是共同的。
微信的方案是:
  1. 在网页生成这个二维码的时候,网页就开始用ajax长轮询,对服务器请求这个UID的扫描记录,如果没有,在特定时长后(目前是27秒左右)会接到状态码408,表示应该继续下一次请求,如果接到201,那么就进入第3步
  2. 什么时候有201呢,微信客户端一旦扫描了这个二维码,就会向解出来的网址发起请求,通知扫描成功(当然这个网址做了来源验证)。服务器一接收到这个请求,就从当前的查询长连接里面立即把201返回过去(如果一直没有请求,那么会在30秒内把408返回去,这就是1里面提到的两个状态码的由来)
  3. 得到状态码201后,通知服务器,客户端由此也进入一个新的页面(就是那个要你点确认的按钮),原理跟上一步相同(长轮询)。这个时候你只要点击确认,服务器就开始给该客户端的用户进行自动登录,并把用户信息在这一步通过当前的某个上行的长轮询给返回出去。当然返回的方式不再是什么状态码了,而是header里面的Set-Cookie,咋就内容其实也相当于状态码:0OKxxxx
  4. 这个时候浏览器就可以成功地用微信认可的任何一种认证方式(通过返回的skey和cookie里面的信息)来请求用户数据了。
之所以要提一下airdroid,是因为它在有些地方是不同的,所以,扫描二维码登录这回事,在保证安全的情况下,实现方式是看你的想象力了。
  1. 首先,扫描二维码只得到字符串而不是网址,避免了鉴权网址外泄
  2. 其次,浏览器是能用web socket来和服务器进行通讯的,避免了长轮询(微信是考虑到中国用户的浏览器不支持ws的居多吧。这里可以顺便介绍一下微软的signalR方案,它可以根据客户端浏览器的支持情况进行自动从ws降到long pool,微信团信应该是看到这个需求没多大的意义,干脆直接用最原始的实现吧,毕竟不是做一个库)
  3. 更多细节我就懒得跟踪了,哪天自己也有同样的需求再研究吧
发布于 2014-03-27 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
29赞同反对,不会显示你的姓名
朱立雄,产品人
李胜龙知乎用户、姚愿 
这个我暂时没发现有人答对的,其实原理很简单:
1. 每打开一次http://wx.qq.com页面的时候会随机生成一个含有唯一uid的二维码,每次刷新页面都会不一样(这个可以保证一个uid只可以绑定一个账号和密码,如果一个uid可以绑定多个账号和密码,那么很可能你的电脑会登陆别人的微信哦);
2. 当用户使用登陆后的微信扫描该二维码的时候,会将这个id和手机上的微信账号及密码绑定,并上传到http://login.weixin.qq.com服务器;
3. http://wx.qq.com页面每隔1秒或2秒会get请求该id对应的微信账号及密码,如果id绑定上了微信账号和密码,那么就可以请求到账号和密码,就可以自动登陆了。

如果大家感兴趣的话,可以继续往下看,我再补充两点:
1. 其实扫描二维码登陆只是在一端未登录的情境下使用会非常方便,同时安全性非常高,因为账号和密码不会暴露给黑客,几乎不存在盗号的可能性,所以我们看到扫描二维码登陆已经使用到了腾讯qqPC客户端最新版本中。
2. 手机扫描二维码登陆还解决了PC和电视端登陆输入麻烦的问题,尤其是电视端的账号和密码通常是要靠遥控器一个一个按出来,所以,扫描二维码登陆在电视端的登陆上也有了比较好的体现,乐视超级电视应该是首次实现这一功能。
3. 如果PC端(或电视端,主要指乐视超级电视最新的系统中也加入了扫描二维码登陆功能)和手机客户端都同时保持登陆的情境下,并且都通过唯一id绑定,那么其中一端可直接远程控制另一端,未来在这一领域的产品想象空间非常大,例如,乐视播放页的1080P速递下载,以及腾讯手机管家的遥控PC离线的功能。
编辑于 2013-09-14 10 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
1赞同反对,不会显示你的姓名
知乎用户,非典型性程序员
知乎用户 赞同
虽然说不清楚具体的原理,但我可以肯定这里面没有什么高深的技术,因为我所带领的开发团队前段时间模仿过这个功能,已经用在了公司业务系统的登录上,安卓版和iOS版都做出来了,也没用多长时间。
具体的技术细节我没有关注,但是我们是一个小公司的小团队,水平也一般,没觉得这个有难度,对大公司来说应该都不算个事。
发布于 2014-03-29 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
知乎用户,+
 
这是“冲击-响应”式的验证机制

腾讯现在网页上扔出一个随机数A
客户端把这个随机数A和客户端自己的Auth Key一同返回

腾讯利用A和Auth Key建立一个唯一的Session ID 按照@朱立雄 的说法,A直接承担了Session ID的职能,我想这是因为HTTPS保证了A不会让第三方看到,因此A是一个Secret

然后网页版的微信走的是可靠的HTTPS
附加说一个,腾讯很好,让https://wx.qq.com采用了TLS1.2,TLS1.2可以抵御BEAST等早先TLS版本中出现的弱点

如此就能确保正确的用户安全地使用了网页版微信
编辑于 2013-09-14 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
1赞同反对,不会显示你的姓名
知乎用户,BSNS PM
起子 赞同
  1. 打开微信网页版微信网页版,在浏览器生成二维码,二维码中包含登录信息和服务端给它生成了一个唯一标识码UUID,同时服务端监听服务端登录请求;
    html:
    https://login.weixin.qq.com/qrcode/3aea191f78ec42?t=webwx">
    jslogin.js:
    window.QRLogin.code = 200; window.QRLogin.uuid = "3aea191f78ec42";
  2. 在客户端使用扫一扫登录网页版时,此时uid已经登录且有访问授权码access_token信息
  3. 扫描网页的二维码,获取到服务器生成的UUID,然后将access_token及UUID发送给服务端
  4. 服务端验证通过后,生成登录授权码并且通知网页端
  5. 网页端获得授权码后即可向服务器申请用户登录信息,完成登录
原文地址:http://www.withink.net/wx_qr_login/
发布于 2014-03-03 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
3赞同反对,不会显示你的姓名
知乎用户,不撕!→ http://wx.icoa.cn
王宝丰joyong知乎用户 赞同
排名第一的我觉得不对,二维码里面是不会包含uid的,只是一个随机不重复的数。
微信扫描之后会把这个数跟服务器进行比对,肯定只有一个唯一的页面是相对应的,那么PC端就会有提示。
这个当然是非常安全的,因为登陆验证是个闭环,是在微信跟服务器之间进行的,外界是无法知道真正的算法的。
发布于 2014-03-25 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
1赞同反对,不会显示你的姓名
匿名用户
知乎用户 赞同
我猜是给每个人的二维码都包含unique的id,这样扫了二维码之后,连带账户信息一起发到服务器端,服务器拿到消息之后就能更新网页端了。
我拿自己的快拍二维码扫了一下,发现是一个https://login.weixin.qq.com/XXXXXXXXXXXXX 这样的链接...每次登录的xxxxxxxx应该都不一样吧
大概是这么一回事吧。
发布于 2012-07-20 1 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
1赞同反对,不会显示你的姓名
Viking赵 赞同
请参考我在CSDN回答的答案, 以及我的具体实现 www(dot)88jimo(dot)com
楼上说随机数的显然是错误的, 随机数有碰撞的可能, uuid 或者 某个全局自增量 还差不多.

扫码登陆是一个小概率事件. 不论long pull还是轮询还是web socket也好, 不是这个方案的key point, 只不过long pull 和web socket是更优化的一个选择而已.

第三方网站微信扫二维码登录的功能是怎么实现的?-CSDN论坛-CSDN.NET-中国最大的IT技术社区

微信在上个礼拜正式公开 登陆API 内测, 可以参考以下页面:
微信开放平台
发布于 2014-07-07 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
1赞同反对,不会显示你的姓名
ULiiAn,请叫我ULiiAn·喵
董崇乐 赞同
抓个包什么都搞得清,没事看看我大中通用户中心,快速登录里照样支持微信扫码登录!http://my.zto.cn
发布于 2014-09-01 1 条评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
陈德隆,喜欢研究文化
 
其实很简单,二维码内容就是一串识别字符串,存在数据库里,照了之后发给微信服务器核对,识别身份,登录页面采用 AJAX 监听,身份识别完成给浏览器发送登录 Cookie。WeCenter 程序自己也实现了一套方法,有兴趣的可以下载源码看看:http://wenda.wecenter.com 登录页面按微信图标就是扫码登录
发布于 2014-03-25 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
李坤,知乎上最后一个普通用户
 

在电脑上使用微信时,你可能已经发现微信不提供传统的账号密码登陆,取而代之的是通过扫描二维码进行登陆。今天就要研究下次登陆方式微信时如何实现的?

1、每次用户打开PC端登陆请求,系统返回一个唯一的uid,并将uid的信息绘制成二维码返回给用户。这里的uid一定是唯一的,否则就会造成你登陆了其他用户的账号或者其他用户登陆你的账号。

2、当用户使用登陆后的微信扫描该二维码的时候,会将这个uid和手机上的微信账号及密码产生的token进行绑定,并上传到http://login.weixin.qq.com/

3、WEB通过JS不断的向后端发起请求,查询有没有关于uid的登陆记录(uid和token是否存在于服务器上)。实现代码可以从微信页面获取:


    function _poll(_asUUID) {
        var _self = arguments.callee,
            _nTime = 0;
        _sCurUUId = _asUUID;
    _logInPage("_poll Request Start, time: " + new Date().getTime());
    _nTime = new Date().getTime();
    $.ajax({
    type: "GET",
    url: "https://login." + _sBaseHost + "/cgi-bin/mmwebwx-bin/login?uuid=" + _asUUID + "&tip=" + show_tip,
    dataType: "script",
    cache: false,
    timeout: _nAjaxTimeout,
    success: function(data, textStatus, jqXHR) {
        _logInPage("_poll Request Success, code: " + window.code + ", time: " + (new Date().getTime() - _nTime) + "ms");
        switch (_aoWin.code) {
        case 200:
            _sSecondRequestTime = new Date().getTime() - _sSecondRequestTime;
            _logInPage("Second Request Success, time: " + _sSecondRequestTime + "ms");
            clearTimeout(_oResetTimeout);

            $.get(_aoWin.redirect_uri + "&fun=new", function(msg) {
                _logInPage("new func reponse, reponseMsg: " + msg);
                _reportNow("new func reponse, reponseMsg: " + msg);
                var code = msg.match(/<script>(.*)<\/script>/);
                if(code){
                    eval(code[1]);
                }else{
                    $("#container").show();
                    $("#login_container").hide();
                }
            });

            _reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Success, uuid: " + _asUUID + ", time: " + _sSecondRequestTime + "ms");
            break;

        case 201:
            clearTimeout(_oResetTimeout);
            show_tip = 0;
            $('.errorMsg').hide();
            $('.normlDesc').hide();
            $('.successMsg').show();
            _logInPage("First Request Success");
            _reportNow("/cgi-bin/mmwebwx-bin/login, First Request Success, uuid: " + _asUUID);

// setTimeout(function(){
_logInPage("Second Request Start");
_reportNow("/cgi-bin/mmwebwx-bin/login, Second Request Start, uuid: " + _asUUID);

                _sSecondRequestTime = new Date().getTime();

                _nAjaxTimeout = 5 * 1000;
                _self(_asUUID);

// }, 500);
break;

        case 408:
            setTimeout(function(){
                _self(_asUUID);
            }, 500);
            break;

        case 400:
        case 500:
            _reset();
            _afterLoadWebMMDo(function(){
                _aoWin.Log.d("500, Login Poll Svr Exception");
            });
            break;
        }
    },
    error: function(jqXHR, textStatus, errorThrown) {
        if (textStatus == 'timeout') {
            setTimeout(function(){
                _self(_asUUID);
            }, 500);
        } else {
            setTimeout(function(){
                _self(_asUUID);
            }, 5000);

            _logInPage("_poll Request Error:" + textStatus);
            _afterLoadWebMMDo(function(){
                _aoWin.Log.e("Login Poll Error:" + textStatus);
            });
        }
    }
    });
}

网页客户端每500毫秒就向服务器发起ssl请求,请求当前二维码的登陆信息,如果返回结果201,则说明已经获取扫描二维码终端相同的账号登陆授权,当返回其他结果时,将在500毫秒之后重新发起请求。

类似微信登陆场景应用场景还是很多,比如通过二维码进行设备间的授权。比如使用手机遥控 装有android系统的电视盒等。

发布于 2014-03-25 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
胡伯特,@tencent APP
 
简单的说,原理就是将同一账号在 手机APP(微信)中 的登陆状态 共享 给 网页 使用。

二维码中只包含需要的共享帐号信息(不含密码);手机拍摄二维码后将手机中的帐号、登录态提交到服务器;服务器校验后存储在统一的登陆态SESSION节点中;网页通过在SESSION读取相应的需要登录的帐号信息。

具体的技术流程是基于Kerberos协议,通过二维码传递手机端的登录Ticket给网页:
1.根据时间戳、路由和SALT指等参数生成一个随机的唯一uid,到服务器请求生成二维码图片,这个uid是登录流程的唯一标识,不可伪造,串联整个登录流程,另外,二维码的生成和访问都是通过SSL安全通道完成的;
2.网页获取到二维码,用这个唯一的uid和server建立长连接;
3.手机照一下也就是App扫描二维码时,手机绑定用户的uin和从二维码中获取到的uid;
4.手机也就是App中点击确认,根据手机的登录态生成Ticket,和uin、uid等参数传递给登录服务器;
5.登录服务器校验登陆态无误后,更新到通过uid指定的session节点,将结果通过长连接传递给网页,或者由网页定时查询session的指定位置获取是否登录;
6.网页校验ticket确认登录;
发布于 2014-03-26 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
和木,技术合伙人
 
每隔一段时间进行请求服务器,返回201 表示成功 408失败
这是我观察的包
前3个都是我等待状态,最后一个我扫了,返回了201。服务端唯一标识验证不解释。
发布于 2014-03-31 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
 

看着答案最后就变成讨论到底是长连接还是轮询的问题,然后就偏了,其实具体用什么技术在这里不是特别重要(长连接也好、Server-Sent Event也好、WebSocket也好、轮询也好,这些都只是途径),提主想知道的是这两个事件是怎么联系的。


表面上的步骤如下:

  1. [电脑] 打开http://wx.qq.com,得到二维码
  2. [手机] 点开扫一扫,扫描PC端二维码,并且扫描成功
  3. [电脑] 提示扫描成功,[手机] 询问是否确认登陆
  4. [手机] 确认登陆(如果不确认登陆么,[电脑]就还是那样)
  5. [电脑] 跳转

其实对应的内部机制差不多是这样的:

  1. 电脑请求网页后,微信服务器生成一个唯一的ID(这里是UUID)给客户端网页,客户端定时发起向微信服务器的连接(这里类似于轮询),微信服务器保持这个连接(这里类似于长连接),保持一段时间(大概27秒)返回一个“还没人扫码”的标识,于是客户端再开连接
  2. 手机微信扫码并解码,解码出来是一个URL也好,是一段文本也好,总之这段东西匹配了手机微信登陆网页版的要求,于是手机微信带着解码出来的信息去请求微信服务器。这里就已经达到了特定微信账号和某个特定网页相关联的目的
  3. 电脑这里微信服务器马上在长连接中返回“有人扫码了”的表示并结束连接,网页提示扫描成功,然后打开长连接等待确认登陆的标识;手机这里么则根据二维码的信息打开对应网页确认登陆
  4. 后面其实和前面一样了,手机微信确认登陆的其实就是请求服务器说这个可以登录了,然后服务器给网页的长连接中返回可以登录的标识并结束长连接,然后跳转到消息网页


就算是单一的长连接也是可以的,流程差不多;就算是轮询又怎么样呢(当然服务器开销会大总所周知),大不了就是等到某一条请求下来发现是“有人扫码”然后接下去某一个请求下来是”确认登陆“而已。

这个流程其实是主要的,至于用什么技术是次要的,用什么技术只是手段而已,假设微信这个网页登陆是出现在5年后,那微信肯定会去用标准化的WebSocket。真要讨论的话,微信最后那个还可以不跳转,做成单网页的,这就没有什么讨论的意义了。

发布于 2014-07-22 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
0赞同反对,不会显示你的姓名
学习了 第一看见是 淘宝支付 时候,出现手机支付 扫下手机支付开始了,当时懵了,现在才明白
发布于 2014-11-23 添加评论 感谢 
分享
 收藏  没有帮助  
举报
  作者保留权利
 
 

以下是我的分析结果,供大家参考,不正确的地方望指正。

用户打开网页版微信: 微信网页版,微信为用户生成了一张包含uuid的二维码,然后前台向后台发送轮询请求,查询此uuid是否已被绑定上登录签名。但如果uuid尚未绑定登录签名,后台不回立即返回结果,而是会阻塞30秒左右,在30秒内仍未扫描成功,后台会返回一个结果码。结果码的值为408,代表微信客户端尚未扫描。

  • 发送轮询请求,判断uuid是否绑定了用户的登陆签名

  • 如果30秒内用户未扫码,uuid未绑定用户的登陆签名,则后台返回结果码 window.code=408


如果用户30秒内,未完成扫码,则前台会不停的发送请求。一旦微信扫码完成,后台会直接返回结果,减少等待时间。扫码成功后,后台会返回结果码window.code=201.
微信客户端扫码二维码后,客户端会向服务器发送uuid以及用户信息,以便绑定uuid和用户信息。
  • 微信客户端请求信息

  • 扫码成功界面

扫码成功后,微信客户端会等待用户确认登陆。用户确认登陆后,微信服务端会为用户生成登陆签名,并将此签名与uuid进行绑定。绑定完成后,微信服务端会将此签名信息返回到前台,之后网页版微信便可通过此签名获取用户信息和微信信息。
  • 确认登陆后的网页响应信息

返回的结果码为:window.code=200,代表用户确认登陆成功。接着跳转到网页版微信的登陆页,并携带登陆签名和uuid。微信登陆服务收到这两个参数后,进行校验完成登录,登陆成功后,跳转到网页版微信主页,用户便可以通过网页使用微信了。

--------------------------------------------------------------------------文毕------------------------------------------------------------

微信自身的扫码登陆功能,也可以通过开放接口,供第三方网站或应用使用。集成微信扫码登陆功能,详见我的上一篇文章二维码登陆。如果不想开发代码,可以到我的个人网站:http://it.maerdym.cn/mm_mishu/.查看已完成的微信扫码登陆功能。近期我会开发微信扫码登陆插件,供大家使用。

  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    129 引用 • 793 回帖
  • 二维码
    9 引用 • 22 回帖
  • 登录
    17 引用 • 133 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 旅游

    希望你我能在旅途中找到人生的下一站。

    83 引用 • 894 回帖
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 45 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 8 关注
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    37 引用 • 24 回帖 • 1 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 428 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    5 引用 • 15 回帖 • 223 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 3 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    124 引用 • 580 回帖
  • 笔记

    好记性不如烂笔头。

    303 引用 • 777 回帖
  • Rust

    Rust 是一门赋予每个人构建可靠且高效软件能力的语言。Rust 由 Mozilla 开发,最早发布于 2014 年 9 月。

    57 引用 • 22 回帖 • 1 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    207 引用 • 2031 回帖
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 247 回帖 • 210 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    534 引用 • 671 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 499 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 1 关注
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    21 引用 • 22 回帖
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 31 关注
  • 导航

    各种网址链接、内容导航。

    37 引用 • 168 回帖
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 596 关注
  • Chrome

    Chrome 又称 Google 浏览器,是一个由谷歌公司开发的网页浏览器。该浏览器是基于其他开源软件所编写,包括 WebKit,目标是提升稳定性、速度和安全性,并创造出简单且有效率的使用者界面。

    60 引用 • 287 回帖
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 151 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    673 引用 • 535 回帖
  • 分享

    有什么新发现就分享给大家吧!

    240 引用 • 1729 回帖 • 1 关注
  • 博客

    记录并分享人生的经历。

    270 引用 • 2386 回帖
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    164 引用 • 594 回帖 • 1 关注
  • VirtualBox

    VirtualBox 是一款开源虚拟机软件,最早由德国 Innotek 公司开发,由 Sun Microsystems 公司出品的软件,使用 Qt 编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。

    10 引用 • 2 回帖 • 1 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 434 关注