扫码登录流程及状态流转分析

634 阅读4分钟

扫码登陆业务流程

image.png

整体设计

  • 服务设计

    扫码登录本身涉及到的服务不多,我们重点关注的可能就是一个登陆模块的服务

    另外会有一个网关服务,这个是任何业务都有的

    除了服务本身,还会涉及到两个不同的需要区分开的设备端:PC端和手机端

    PC端是需要登录的一方,手机端是已经登录的,要通过扫码帮助PC登陆的一方

  • 存储设计

    我们要存的是二维码信息,在扫码登录过程中,这个二维码是不断变化的, 最终确认之后

    会生成一个 PC Token,一个设备的登录凭证就是一个Token,也就是一个设备一个Token

    登录的时候就是用这个Token进行鉴权登录,这里我们看不到什么需要关系型查询的地方,应该用kv存储

流程分析

image.png

  1. PC端向登录服务申请二维码ID,从返回中拿到二维码ID
    • 产生一个二维码ID,关联二维码ID和设备信息记录到Redis
  2. 生成和展示二维码
    • 同个二维码ID在二维码服务生成二维码URL,PC端展示出二维码,PC端轮询二维码状态
  3. 移动端扫二维码,拿到二维码ID
    • 移动端发起扫码请求,请求到达服务端,通过二维码ID拿到关联的设备信息,更新二维码状态,生成临时Token
  4. 确认登陆
    • 使用临时Token确认登录,生成登录用的PC Token,把PC Token与二维码ID进行关联,更新二维码状态为已激活

要点分析

Redis信息存储

一开始申请二维码ID的时候,会生成一个二维码ID,关联PC设备信息,还会记录Status状态信息,此时是待扫码

随着扫码操作的进行,状态信息发生变化,Status -> 待确认

确认登录之后,状态信息发生改变,Status -> 已激活

所以整体来说Redis信息的存储内容是有三个阶段:生成时 -> 扫码时 -> 确认后

  • 生成时Redis数据

    key是二维码ID,value会复杂一点,我们抽象一下,主要就是两个数据

    一个是DeviceInfo,即设备信息,设备ID等,我们可以看作一个整体

    另一个是状态信息,,状态从生成 -> 待确认 -> 已激活 -> 关闭

public class DeviceInfo {
		String deviceId;   // 设备ID
		String deviceType; // 登录设备类型,iphone、mac...
		String position;	 // 登录地址
}
{
		"qrIdxxx": {
				"deviceInfo": {
						"deviceId": "sdfsfaldfhfshlfhds",
						"deviceType": "mac",
						"position": "guangzhou"
				},
				"status": 1 //待扫码
		}
}
  • 扫码后Redis存储

    扫码之后,在我们的电脑上可以看得到基本的用户信息,比如头像

    这说明扫码的时候,是将账户信息传递过去了,很多实现里就是传递一个账户ID,PC拿到之后通过ID获取基本信息

    这时候,Token的状态就会从待扫码变成待确认,整体内容变成这样:

{
		"qrIdxxx": {
				"accountId": "dsfsd1231321f",
				"deviceInfo": {
						"deviceId": "sdfsfaldfhfshlfhds",
						"deviceType": "mac",
						"position": "guangzhou"
				},
				"status": 2 //待确认
		}
}

​ 同时,在扫码之后,还会生成一个临时Token,临时Token关联手机端设备信息

{
		"tmpToken...": {
				"deviceInfo": {
						"deviceId": "sdfsfaldfhfshlfhdz",
						"deviceType": "iphone",
						"position": "guangzhou"
				},
		}
}
  • 确认后Redis存储

    最后确认之后,Token对应的变为已激活

    此时tmpToken也会被删除

{
		"qrIdxxx": {
				"accountId": "dsfsd1231321f",
				"deviceInfo": {
						"deviceId": "sdfsfaldfhfshlfhds",
						"deviceType": "mac",
						"position": "guangzhou"
				},
				"status": 3 //已激活
				"pcToken": "xxxxxx"
		}
}

安全性考虑

  • 设备关联设计

    这里有个细节设计,就是Token是有关联设备信息的

    为什么要这样设计呢?目的是在于希望一个Token只能适用于一个设备

    这样就算是Token泄露了,只要坏人不知道你的设备信息,依然无法登录,多一层保障

    所以在后面登录的时候,会传递设备信息用来进行安全校验

  • 临时Token设计

    为什么需要临时Token的设计呢?对应到这个操作流程就是,为什么会有个确认登录的流程

    直接扫码不就可以了吗?这里最主要还是产品的考虑,确认流程是必要的

    你不小心扫了一下,就直接登录了,这多危险,很多厂家还加上几秒时间让你看清楚设备信息、地址等才能确认

    正是因为有确认登录的这个逻辑,所以才需要临时Token,这样我们才能将确认和扫码关联起来

    请求中携带了临时Token,只在扫码的时候返回给了手机端,通过这个凭证,可以一定程度上证明扫码的是你,确认的还是你

  • 过期时间设计

image.png