实现扫码登录

92 阅读2分钟

参考:blog.csdn.net/qq_41698074…

登录原理

image.png

  1. 用户打开 Web 端网页,进入扫码登录的界面;
  2. 从 Web 端服务器获取二维码的图并获取其状态;
  3. Web 端服务器在生成二维码时,会生成一个 uuid 和二维码进行关联,并将 uuid 存入 db 记录中;
  4. 用户打开 APP 端,对着二维码进行扫码授权操作;
  5. APP 客户端从二维码中读取到 uuid,带着 APP 内的身份信息访问 APP 端服务器;
  6. APP 端服务器获取到用户的身份信息后,将用户 id 更新到 db 中对应 uuid 的记录中,此时 Web 服务器就能拿到对应的用户 id,之后生成登录身份信息返回给浏览器,即用户在 Web 端完成了登录;

基于以上分析,我们可以将扫码登录分为两个步骤:获取扫码状态和获取用户登录信息。

获取扫码状态的三种方案

  • 长链接
    • 优点:
      • 减少资源浪费
      • 比轮询响应速度快
    • 缺点
      • 占用服务端大量连接数
  • 轮询
    • 优点:
      • 开发易维护
      • 更快释放连接
    • 缺点
      • 产生大量无效访问
  • 长轮询
    • 优点
      • 结合了长链接和轮询的优点削弱了缺点
    • 缺点
      • 开发起来更加复杂,相当于实现了两种方案

目前主流方案是定时轮询,这是由于扫码登录本身也是低频操作,并不会造成很大量的请求,但优点又比较突出。

实现

onMounted 获取二维码信息

接口返回url

生成二维码【QRCode.toDataURL()生成二维码图片链接】

轮询二维码状态【调用轮询接口,已扫码确认,清除轮询,获取用户信息】

轮询

清除轮询
// 获取二维码信息
const getQRInfo = () => {
postV1QrInfo({ app_id: 3, source: "web" }).then((res) => {
  console.log(res);
  generateQRcode(res.data.login_url);
  QRinfo.value = res.data;
  checkQRcode();
  timer = setInterval(() => {
    checkQRcode();
  }, 1000 * 11);
  timeOut = setTimeout(() => {
    clearCheck(true);
  }, 1000 * res.data.timeout);
});
};
// 生成二维码
const generateQRcode = (url: string) => {
 QRCode.toDataURL(url, { width: 280, height: 280, color: { dark: "#6697f1", light: "#fff" } })
   .then((res: any) => {
     // 生成的二维码链接
     code.value = res;
   })
   .catch(() => {});
};
// 清除轮询
const clearCheck = (codeStatus: boolean) => {
  isExpired.value = codeStatus;
  clearInterval(timer);
  clearTimeout(timeOut);
};
// 轮询二维码状态
const checkQRcode = () => {
  postV1Check({ qr_code: QRinfo.value.qr_code, app_id: 3, source: "web" }).then((res) => {
    console.log(res);
    // 1-未扫码 2-已扫码确认
    if (res.data.status === 2) {
      clearCheck(false);
      userInfoStore.setToken(res.data.jwt);
      getUserInfo();
    }
  });
};