扫二维码登录现在比较常见,比如微信、支付宝等 PC 端登录,并且越来越多的APP支持扫码登录,其中原理如何呢?
PC端Cookie + Session 登录
HTTP 是一种无状态的协议,客户端每次发送请求时,首先要和服务器端建立一个连接,在请求完成后又会断开这个连接。这种方式可以节省传输时占用的连接资源,但同时也存在一个问题:每次请求都是独立的,服务器端无法判断本次请求和上一次请求是否来自同一个用户,进而也就无法判断用户的登录状态。
为了解决 HTTP 无状态的问题,Lou Montulli 在 1994 年的时候,推出了 Cookie。Cookie 是服务器端发送给客户端的一段特殊信息,这些信息以文本的方式存放在客户端,客户端每次向服务器端发送请求时都会带上这些特殊信息。有了 Cookie 之后,服务器端就能够获取到客户端传递过来的信息了,如果需要对信息进行验证,还需要通过 Session。客户端请求服务端,服务端会为这次请求开辟一块内存空间,这个便是 Session 对象。有了 Cookie 和 Session 之后,我们就可以进行登录认证了。
Cookie + Session 实现流程:
-
用户访问com/pageA,并输入密码登录。
-
服务器验证密码无误后,会创建 SessionId,并将它保存起来。
-
服务器端响应这个 HTTP 请求,并通过 Set-Cookie 头信息,将 SessionId 写入 Cookie 中。
Cookie + Session 存在的问题:
-
由于服务器端需要对接大量的客户端,也就需要存放大量的 SessionId,这样会导致服务器压力过大。
-
如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。
-
由于 SessionId 存放在 Cookie 中,所以无法避免 CSRF 攻击。
移动端基于token的认证机制
为了解决 Session + Cookie 机制暴露出的诸多问题,我们可以使用 Token 的登录方式。Token 是服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。
Token 机制实现流程:
用户首次登录时:
-
用户输入账号密码,并点击登录。
-
服务器端验证账号密码无误,创建 Token。
-
服务器端将 Token 返回给客户端,由客户端自由保存。
后续页面访问时:
-
用户访问com/pageB 时,带上第一次登录时获取的 Token。
-
服务器端验证 Token ,有效则身份验证成功。
Token 的优缺点:
-
服务器端不需要存放 Token,所以不会对服务器端造成压力,即使是服务器集群,也不需要增加维护成本。
-
Token 可以存放在前端任何地方,可以不用保存在 Cookie 中,提升了页面的安全性。
-
Token 下发之后,只要在生效时间之内,就一直有效,如果服务器端想收回此 Token 的权限,并不容易。
二维码扫码登录的原理
二维码扫码登录的流程图:
扫码登录可以分为三个阶段:待扫描、已扫描待确认、已确认。
待扫描阶段
待扫描阶段也就是流程图中 1~5 阶段,即生成二维码阶段,这个阶段跟移动端没有关系,是 PC 端跟服务端的交互过程。
每次用户打开PC端登陆请求,系统返回一个唯一的uid,并将uid的信息绘制成二维码返回给用户。这里的uid一定是唯一的,否则就会造成你登陆了其他用户的账号或者其他用户登陆你的账号。
此时在 PC 端会启动一个定时器,轮询查询二维码是否被扫描。如果移动端未扫描的话,那么一段时间后二维码将会失效。二维码增加超时机制之后,会增加攻击者攻击的难度,不过攻击者也可能利用脚本去自动刷新二维码。
已扫描待确认阶段
流程图中第 6 ~ 10 阶段,我们在 PC 端登录微信时,手机扫码后,PC 端的二维码会变成已扫码,请在手机端确认。这个阶段是移动端跟服务端交互的过程。
首先移动端扫描二维码,获取二维码 ID,然后将手机端登录的信息凭证(token)和 二维码 ID 作为参数发送给服务端,此时的手机一定是登录的,不存在没登录的情况。
服务端接受请求后,会将 token 与二维码 ID 关联,为什么需要关联呢?你想想,我们使用微信时,移动端退出, PC 端是不是也需要退出,这个关联就有点把子作用了。然后会生成一个一次性 token,这个 token 会返回给移动端,一次性 token 用作确认时候的凭证。
PC 端的定时器,会轮询到二维码的状态已经发生变化,会将 PC 端的二维码更新为已扫描,请确认。
二维码扫描一定要有这个确认的页面,明确告知用户要做的操作,假设没有确认这个环节,那么是极其容易上当的。另外,二维码扫描确认之后,再往用户app或手机等发送登录提醒的通知,告知如果不是本人登录的,则建议用户立即修改密码
已确认
流程图中的 第 11 ~ 15 步骤,这是扫码登录的最后阶段,移动端携带上一步骤中获取的临时 token ,确认登录,服务端校对完成后,会更新二维码状态,并且给 PC 端生成一个正式的 token ,后续 PC 端就是持有这个 token 访问服务端。