• web扫码登录


    需求

    pc端实现app扫码登录

    流程

    交互流程

    在这里插入图片描述

    服务交互流程

    在这里插入图片描述

    关键思路

    主要问题在于如何识别APP端用户,然后传递给PC端已经登录成功

    通过记录标记扫描唯一二维码与用户进行关联,在PC端查询时已绑定通过返回的绑定数据进行登录。这里查询可以使用轮询/长连接,返回绑定的数据主要用于请求返回登录后需要的信息

    代码

    生成二维码,返回给PC展示

    注意返回二维码唯一标识可以进行加码,防止不必要的安全问题

        /**
         * pc 获取二维码
         *
         * @return
         * @throws IOException
         */
        @Override
        public ScanningCodeDto getLoginScanningCode() throws IOException {
           //两个字段key二维码标识,code 二维码
            ScanningCodeDto codeDto = new ScanningCodeDto();
            String primitiveKey = StrKit.uuid();
            //hutool包构建aes加密
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, ScanningCodeLoginConstant.CODE_SECRET_KEY.getBytes(StandardCharsets.UTF_8));
            //加密为16进制表示
            String key = aes.encryptHex(primitiveKey);
            codeDto.setKey(key);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            //二维码内容也为加密内容
            QrCodeUtil.generate(key, 300, 300, null, baos);
            // 进行Base64编码
            String code = Base64.encode(baos.toByteArray());
            baos.flush();
            codeDto.setCode(code);
            //redis存储信息,5分钟过期
            ScanningCodeInfoVo scanningCodeInfoVo = new ScanningCodeInfoVo();
            scanningCodeInfoVo.setKey(key);
            scanningCodeInfoVo.setCode(code);
            scanningCodeInfoVo.setStatus("1");
            //设置到redis,key和过期时间可以根据自己情况设置
            redisUtils.set( primitiveKey, scanningCodeInfoVo, 60 * 5);
            return codeDto;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    二维码包含信息能识别即可,可以是url也可以是标识。返回二维码时同时返回唯一标识来标记查询时是哪个二维码

    轮询查询二维码状态

     /**
         * 查询二维码状态
         *
         * @param key 二维码唯一标识
         * @return
         */
     @Override
        public ScanningCodeStatusDto getScanningCodeStatus(String key) {
            //解密为字符串
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, ScanningCodeLoginConstant.CODE_SECRET_KEY.getBytes(StandardCharsets.UTF_8));
            String primitiveKey = aes.decryptStr(key, CharsetUtil.CHARSET_UTF_8);
            //查询redis二维码信息
            ScanningCodeInfoVo scanningCodeInfoVo = (ScanningCodeInfoVo) redisUtils.get(primitiveKey);
            if (Objects.isNull(scanningCodeInfoVo)) {
                //返回已过期
                throw  new Exception("二维码已过期");
            }
            //成功后登录
            String status = scanningCodeInfoVo.getStatus();
            ScanningCodeStatusDto codeStatusDto = new ScanningCodeStatusDto();
            //已扫描
            if (Objects.equals("2", status)) {
                //构建aes加密,加密用户id为16进制表示
                codeStatusDto.setKey(aes.encryptHex(scanningCodeInfoVo.getUserId() + ":" + scanningCodeInfoVo.getUserName()));
                codeStatusDto.setStatus("2");
                return codeStatusDto;
            }
            codeStatusDto.setStatus("1");
            return codeStatusDto;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    有些系统使用长连接,也可以。 注意这里可以加个锁,避免多台设备扫描到一个码。

    APP扫码请求

     /**
         * 扫描二维码
         *
         * @param dto
         * @return
         */
        @Override
        public String scan(ScanningCodeDto dto) {
            //获取对应二维码信息
            SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.AES, ScanningCodeLoginConstant.CODE_SECRET_KEY.getBytes(StandardCharsets.UTF_8));
            String primitiveKey = aes.decryptStr(dto.getKey(), CharsetUtil.CHARSET_UTF_8);
            //查询redis二维码信息
            ScanningCodeInfoVo scanningCodeInfoVo = (ScanningCodeInfoVo) redisUtils.get(primitiveKey);
            if (Objects.isNull(scanningCodeInfoVo)) {
                //返回已过期
                throw new Exception("二维码已过期");
            }
            //成功后登录
            String status = scanningCodeInfoVo.getStatus();
            if (Objects.equals("2", status)) {
                //二维码已经使用
                throw new Exception("二维码已经使用");
            }
            //标记二维码信息,标记状态已经使用
            scanningCodeInfoVo.setStatus("2");
            scanningCodeInfoVo.setUserId(teasUserSession.getUserId());
            scanningCodeInfoVo.setUserName(teasUserSession.getUserName());
            //修改redis中二维码信息
            redisUtils.set(primitiveKey, scanningCodeInfoVo, 60 * 5);
            //返回二维码情况
            return ”登陆成功“;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    登录

    轮询查询到已经扫描并且获取到用户信息后,几个方案都可以

    1. 调用特定的登录接口进行登录,通过返回的key包含的加密信息进行登录(我这里的使用)
    2. 轮询接口查询到已经扫码,获取用户信息直接后台登录
    3. 返回加密后的账号密码调用原有的登录接口(和第一种差不多)

    根据自己的情况进行处理即可

    总结

    扫码登录流程大差不差,主要解决的问题

    1. 谁扫了码,如何去识别用户扫码
    2. pc如何获取用户信息并达成登录

    有问题欢迎一起探讨个人信息联系我.

  • 相关阅读:
    原三高搜索条件-多选问题
    可视化剪辑,账号矩阵管理,视频分发,聚合私信多功能一体化营销工具 源代码开发部署方案
    (9)点云数据处理学习——Global registration(全局注册)
    Maven
    24. python 字符串索引取值
    Django框架之介绍与启动
    接口访问量统计
    Deformable Convolutional Networks 可变形卷积网络论文精读与解析
    上海市青少年算法2022年11月月赛(丙组)
    【ROS2原理17】ROS 2 安全飞地
  • 原文地址:https://blog.csdn.net/qq_28325291/article/details/128102355