最近做完扫码登陆,记录一下流程;需求:有web端和APP端完整账号登陆,App扫码登陆web端
扫码登陆流程
请求key
生成一个uuid的key返回前端 同时存入redis并初始状态为 0 ,失效时间为三分钟
value 逗号分隔 前面表示状态 (0-未扫码,1-已扫码,2-已登陆)
逗号后面随便放个值,等确认登陆后存用户账号 (手机号)
@ApiOperation(value = "获取二维码登陆初始key")
@PostMapping("/getQrKey")
public R getQrKey() {
log.info("获取二维码登陆初始key");
try {
ValueOperations<String, String> opsForValue = strRedisTemplate.opsForValue();
String key = IdUtil.simpleUUID();
//key - value value 逗号分隔 前面表示状态 (0-未扫码,1-已扫码,2-已登陆) 后面表示userId
opsForValue.set(CommonConstants.QR_REDIS_HEAR + ":" + key, "0,0", 180, TimeUnit.SECONDS);
QrCodeResultVo build = QrCodeResultVo.builder().type("0").key(key).build();
return new R(build);
} catch (Exception e) {
log.error("获取二维码登陆初始key失败", e);
return R.error("获取二维码登陆初始key失败", e);
}
}
APP客户端扫码
APP客户端扫码后,修改对应key的状态
如果状态要修改为2 则在redis存入value时 将用户的账号(手机号)拼接在后面
@ApiOperation(value = "更新key的状态")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "key", dataType = "String", required = true, value = "key"),
@ApiImplicitParam(paramType = "query", name = "status", dataType = "String", required = true, value = "status")
})
@PostMapping("/updateQrStatus")
public R updateQrStatus(@RequestParam(name = "key", required = false) String key,
@RequestParam(name = "status", required = false) String status) {
log.info("更新key的状态,key = {} ,status = {}", key, status);
try {
VillcloudUser user = SecurityUtils.getUser();
ValueOperations<String, String> opsForValue = strRedisTemplate.opsForValue();
//key - value value 逗号分隔 前面表示状态 (0-未扫码,1-已扫码,2-已登陆,3-已过期) 后面表示phone
String value = opsForValue.get(CommonConstants.QR_REDIS_HEAR + ":" + key);
HashMap<String, String> map = new HashMap<>();
if (StrUtil.isBlank(value)) {
//不存在表示已超时
map.put("status", "3");
return new R(map);
} else {
//存在 则修改对应的状态
String[] split = value.split(",");
if ("1".equals(status)) {
opsForValue.set(CommonConstants.QR_REDIS_HEAR + ":" + key, status + "," + split[1], 180, TimeUnit.SECONDS);
} else if ("2".equals(status)) {
opsForValue.set(CommonConstants.QR_REDIS_HEAR + ":" + key, status + "," + user.getPhone(), 180, TimeUnit.SECONDS);
}
map.put("status", status);
}
return new R(map);
} catch (Exception e) {
log.error("更新key的状态失败", e);
return R.error("更新key的状态失败", e);
}
}
轮询查状态
前端拿到key之后 转换成二维码 同时定时轮询向后台请求 key对应的状态 不停刷新 直到状态为 2 (已登录)或者 3(已过期)
@ApiOperation(value = "获取扫码状态")
@ApiImplicitParams({
@ApiImplicitParam(paramType = "query", name = "key", dataType = "String", required = true, value = "key")
})
@PostMapping("/getQrStatus")
public R getQrStatus(@RequestParam(name = "key", required = false) String key) {
log.info("获取key的状态,key = {}", key);
try {
VillcloudUser user = SecurityUtils.getUser();
ValueOperations<String, String> opsForValue = strRedisTemplate.opsForValue();
//key - value value 逗号分隔 前面表示状态 (0-未扫码,1-已扫码,2-已登陆,3-已过期) 后面表示phone
String value = opsForValue.get(CommonConstants.QR_REDIS_HEAR + ":" + key);
HashMap<String, String> map = new HashMap<>();
if (StrUtil.isBlank(value)) {
//不存在表示已超时
map.put("status", "3");
return new R(map);
} else {
//存在 则返回对应的状态和token
String[] split = value.split(",");
map.put("status", split[0]);
}
return new R(map);
} catch (Exception e) {
log.error("获取扫码登录扫码状态失败", e);
return R.error("获取扫码登录扫码状态失败", e);
}
}
登录流程
如果返回的状态为2 则走登录流程