实现步骤
- 用户访问web端,选择扫码登录。此时生成二维码+二维码的图片地址展示。
- app端扫码(登录状态),传输用户token和二维码。二维码切换展示状态(待确认)
- 用户确认后,web端生成新的token信息。删除二维码的相关数据。
具体实现
web端展示二维码
@Autowired
private StringRedisTemplate redisTemplate;
@PostMapping("create")
@ResponseBody
public LoginQrcodeVO createLoginQrcode() {
String code = RandomUtil.randomString(6);
redisTemplate.opsForValue().set(code, "", 3, TimeUnit.MINUTES);
String imgUrl = "d:/qrcode.jpg";
QrCodeUtil.generate(code, 300, 300, FileUtil.file(imgUrl));
return new LoginQrcodeVO(code, imgUrl);
}
app扫码
private BaseResult handleQr(String code, String token) {
boolean isLegal = JwtUtils.verify(token);
if (!isLegal) {
return BaseResult.error(AUTHENTICATION_FAILED);
}
String username = JwtUtils.getUsername(token);
CodeVO codeVO = CodeUtils.getConfirmingCodeInfo(username, DEFAULT_AVATAR_URL);
redisCache.setCacheObject(code, codeVO, DEFAULT_QR_EXPIRE_SECONDS, TimeUnit.SECONDS);
LoginInfoVO loginInfoVO = new LoginInfoVO(address, browser, os, tmpToken);
return BaseResult.success(SCAN_SUCCESS, loginInfoVO);
}
确认登录
private BaseResult confirmLogin(String code, String token) {
String username = JwtUtils.getUsername(token);
String formalToken = JwtUtils.sign(username);
CodeVO codeVO = CodeUtils.getConfirmedCodeInfo(username, DEFAULT_AVATAR_URL, formalToken);
redisCache.setCacheObject(code, codeVO, DEFAULT_QR_EXPIRE_SECONDS, TimeUnit.SECONDS);
return BaseResult.success(CONFIRM_SUCCESS);
}
前端互动
- 使用定时器轮询获取二维码的状态
- 使用
websocket
,当app端扫码ok后,更新二维码的展示;当app确认登录,跳转首页。