扫码登陆原理

前言

在网上看别人的面经的时候,发现一个有意思并且自己从来没有思考过的问题:生活中,我们登陆淘宝或者微信时又是可以选择"扫一扫"登陆,这背后的原理是什么? 这个问题由于自己已经习以为常了,竟然从来没有认真思考过其背后的原理,这个问题甚至可以延伸的去想一想,大家在支付的时候也可以提供扫一扫支付,这背后的原理是什么?
先回到最开始的问题上,如果是自己在面试,我觉得自己会这样回答:由于二维码包含的信息非常多,针对同一个登陆请求,在一定时间段内网站就会返回一个二维码用来提供登陆服务;用户用手机扫描后会将已经登陆的账号密码信息发送至这个二维码包含的链接地址上,该链接地址实质上就是正常的账号密码登陆链接地址,将账号和密码传至服务器就可以执行登录操作了。如果面试官再问为什么还会有"请在手机上确认登陆"这一选项,我觉得可能是一种防范措施吧,害怕误扫了二维码执行了不必要的登录操作。虽然这样子回答,但是还是有些点没有弄清楚的,所以下面正式介绍一下原理。

扫码登陆原理

参照了这篇博客
以淘宝登陆为例,登陆淘宝的界面:https://login.taobao.com/member/login.jhtml 传回来的参数为:
2018-10-21_15-27-59.png

_ksTS	1540106755738_2768
callback	jsonp2769
defaulturl	
lgToken	2c3b4d53ef0513787bf4ce711ea5ba53

然后请求(GET)报文是这样的:

https://qrlogin.taobao.com/qrcodelogin/qrcodeLoginCheck.do?lgToken=2c3b4d53ef0513787bf4ce711ea5ba53&defaulturl=&_ksTS=1540106757739_2804&callback=jsonp2805

关键的就是lgToken,是网页的唯一ID,当打开了二维码登录的时候,网页在轮询(应该是长轮询long polling)调用接口去请求服务器。如果没有扫码,返回的为:
2018-10-21_16-00-58.png
如果扫了的话则会返回

{
    "code": "10001",
    "message": "mobile scan QRCode success",
    "success": true
}

长时间没有扫码的话,网页端会停止轮询,二维码失效!当手机端确认登陆后,接口返回的是:

{ "code": "10006", "success": true, "url": "https://login.taobao.com/member/loginByIm.do?uid=cntaobaoxxx&token=ff82fc0d1d395a33d3b38ec5a4981336&time=1530179143250&asker=qrcodelogin&ask_version=1.0.0&defaulturl=https://www.taobao.com&webpas=0b7aed2d43f01825183e4a49c6cae47d1479929926"
}

表示登陆成功,当然手机端与服务端在点击"确认登陆"之间的交互可能就是这样:网页端生成的lgToken去请求服务端,服务端记住了这个lgToken并认为登陆了,当网页端再次轮询请求接口时,就返回真正的登陆态Token,网页端此时就可以凭着这个Token来登陆了。

2018-10-21_16-07-12.png

扫码付钱原理

感觉扫码付钱反而比扫码登陆的原理要简单(难道是我的错觉?),只不过在安全系数上扫码付钱做的会好一些,当然什么加密方式我们也无从而知。我觉得扫码支付可能会简单一些的原因是二维码在这里表示的只是个人ID信息,所以二维码不会变,并不像扫码登陆的时候的lgToken与返回的登陆Token呢样复杂。扫码支付的时候分为两种,一种是自己扫别人的码,另一种是商家扫自己的码,但是原理都是相同的,都是要在一个"订单"里填写上买家与卖家的信息ID,而不管是谁扫还是被谁扫,事实上已经提供了这两个信息;最后提交金额,根据ID找到对应用户扣钱就行了,当然这里只谈到扫码支付的大体框架,具体一些实现细节诸如如何确保用户金额被正确扣了或者如果网络状态出现问题导致钱没了,这些都不是扫码支付的原理而是背后需要支持的完备性与安全性所需要考虑的。

关于polling与long polling

提到了轮询与长轮询的概念,铜鼓哦其他博客里的例子简单介绍下:

polling和 long polling的区别:

当浏览器端与服务器建立连接之后,一般有两种方式可以获取到服务器的更新信息,即polling和long polling。
polling即轮询,是指浏览器通过周期性轮询,查看服务器是否有更新的信息;
long polling指的是长轮询,浏览器与服务器建立连接之后,服务器将此连接进行挂起,但有更新信息时,再将信息发送给浏览器端。浏览器端重新建立连接,如此循环反复,这是一种长连接的方式。

借用一个比较形象的例子:

传统的polling一般是由C向S询问:“有我的信件吗?”。S接到询问之后,会立即查询,并且把查询结果告诉C,不管有没有C的信件,要么回复:“嗯,你有X封信。”,要么回复:“没,没有你的信”。

而Long Polling更像是这样,C向S发出询问:“有我的信件吗?”,S开始查询,如果有则回复C:“嗯,有你x封信”。如果没有,则不作任何回复,而是让C等着,自己一遍一遍地查询是否有订阅者的信。

换句话说:当S收到C的查询请求之后,Polling则只查询一次,并且把查询结果告诉C;而Long Polling收到请求之后,则会一遍一遍地查询,直到有消息才会响应C,不然一直hold Client。
优缺点分析:

轮询:客户端定时向服务器发送Ajax请求,服务器接到请求后马上返回响应信息并关闭连接。 
优点:后端程序编写比较容易。 
缺点:请求中有大半是无用,浪费带宽和服务器资源。 
实例:适于小型应用。


长轮询:客户端向服务器发送Ajax请求,服务器接到请求后hold住连接,直到有新消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求。 
优点:在无消息的情况下不会频繁的请求,耗费资源小。 
缺点:服务器hold连接会消耗资源,返回数据顺序无保证,难于管理维护。 
原文地址:https://www.cnblogs.com/yunlambert/p/9825469.html