千家信息网

java中SpringBoot框架如何实现扫码登录

发表于:2025-02-07 作者:千家信息网编辑
千家信息网最后更新 2025年02月07日,这篇文章主要介绍java中SpringBoot框架如何实现扫码登录,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!项目简介后端:SpringBoot,Redis。前端:Vue,V
千家信息网最后更新 2025年02月07日java中SpringBoot框架如何实现扫码登录

这篇文章主要介绍java中SpringBoot框架如何实现扫码登录,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

项目简介

后端:SpringBootRedis
前端:VueVue RouterVueXAxiosvue-qrElemntUI
安卓:ZXingXUIYHttp

实现思路

总体的扫码登录和OAuth3.0的验证逻辑相似,如下所示:

用户选择扫码登录可以看作是A:前端发授权请求,等待app扫码。
用户使用app进行扫码可以看作是B:扫码进行授权,返回一个临时Token供二次认证。
用户在app进行确认登录可以看作是C:进行登录确认,授权用户在Web端登录。
后端在用户确认登录后返回一个正式Token即可看作是步骤D
后续前端根据正式Token访问后台接口,正式在Web端进行操作即可看作是EF

二次认证的原因

之所以在用户扫码之后还需要进行再一次的确认登录,而不是直接就登录的原因,则是为了用户安全考虑,避免用户扫了其他人需要登录的二维码,在未经确认就直接登录了,导致他人可能会在我们不知道的情况下访问我们的信息。

实现步骤

用户访问网页端,选择扫码登录

用户在选择扫码登录时,会向后端发送一个二维码的生成请求,后端生成UUID,并保存到Redis(固定有效时间),状态设置为UNUSED(未使用)状态,如果Redis缓存过期,则为EXPIRE(过期)状态,前端根据后端返回的内容生成二维码,并设置一个定时器,每隔一段时间根据二维码的内容中的UUID,向后端发送请求,获取二维码的状态,更新界面展示的内容。

生成二维码后端接口:

/** * 生成二维码内容 * * @return 结果 */@GetMapping("/generate")public BaseResult generate() {    String code = IdUtil.simpleUUID();    redisCache.setCacheObject(code, CodeUtils.getUnusedCodeInfo(),                               DEFAULT_QR_EXPIRE_SECONDS, TimeUnit.SECONDS);    return BaseResult.success(GENERATE_SUCCESS, code);}

前端获取内容,生成二维码:

getToken() {    this.codeStatus = 'EMPTY'    this.tip = '正在获取登录码,请稍等'    // 有效时间 60 秒    this.effectiveSeconds = 60    clearInterval(this.timer)    request({        method: 'get',        url: '/code/generate'    }).then((response) => {        // 请求成功, 设置二维码内容, 并更新相关信息        this.code = `${HOST}/code/scan?code=${response.data}`        this.codeStatus = 'UNUSED'        this.tip = '请使用手机扫码登录'        this.timer = setInterval(this.getTokenInfo, 2000)    }).catch(() => {        this.getToken()    })}

后端返回二维码状态信息的接口:

/** * 获取二维码状态信息 * * @param code 二维码 * @return 结果 */@GetMapping("/info")public BaseResult info(String code) {    CodeVO codeVO = redisCache.getCacheObject(code);    if (codeVO == null) {        return BaseResult.success(INVALID_CODE, StringUtils.EMPTY);    }    return BaseResult.success(GET_SUCCESS, codeVO);}

前端轮询获取二维码状态:

getTokenInfo() {    this.effectiveSeconds--    // 二维码过期    if (this.effectiveSeconds <= 0) {        this.codeStatus = 'EXPIRE'        this.tip = '二维码已过期,请刷新'        return    }    // 轮询查询二维码状态    request({        method: 'get',        url: '/code/info',        params: {            code: this.code.substr(this.code.indexOf('=') + 1)        }    }).then(response => {        const codeVO = response.data        // 二维码过期        if (!codeVO || !codeVO.codeStatus) {            this.codeStatus = 'EXPIRE'            this.tip = '二维码已过期,请刷新'            return        }        // 二维码状态为为正在登录        if (codeVO.codeStatus === 'CONFIRMING') {            this.username = codeVO.username            this.avatar = codeVO.avatar            this.codeStatus = 'CONFIRMING'            this.tip = '扫码成功,请在手机上确认'            return        }        // 二维码状态为确认登录        if (codeVO.codeStatus === 'CONFIRMED') {            clearInterval(this.timer)            const token = codeVO.token            store.commit('setToken', token)            this.$router.push('/home')            Message.success('登录成功')            return        }    })}

使用手机扫码,二维码状态改变

当用户使用手机扫码时(已登录并且为正确的app,否则扫码会跳转到自定义的宣传页),会更新二维码的状态为CONFIRMING(待确认)状态,并在Redis缓存中新增用户名及头像信息的保存供前端使用展示,此外还会返回用户的登录信息(登录地址、浏览器、操作系统)给app展示,同时生成一个临时Tokenapp(固定有效时间)。

用户扫码时的后台处理:

/** * 处理未使用状态的二维码 * * @param code 二维码 * @param token token * @return 结果 */private BaseResult handleUnusedQr(String code, String token) {    // 校验 app 端访问传递的 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);    // 返回登录地址、浏览器、操作系统以及一个临时 token 给 app    String address = HttpUtils.getRealAddressByIp();    String browser = HttpUtils.getBrowserName();    String os = HttpUtils.getOsName();    String tmpToken = JwtUtils.sign(username);    // 将临时 token 作为键, 用户名为内容存储在 redis 中    redisCache.setCacheObject(tmpToken, username, DEFAULT_TEMP_TOKEN_EXPIRE_MINUTES, TimeUnit.MINUTES);    LoginInfoVO loginInfoVO = new LoginInfoVO(address, browser, os, tmpToken);    return BaseResult.success(SCAN_SUCCESS, loginInfoVO);}

手机确认登录

当用户在app中点击确认登录时,就会携带生成的临时Token发送更新状态的请求,二维码的状态会被更新为CONFIRMED(已确认登录)状态,同时后端会生成一个正式Token保存在Redis中,前端在轮询更新状态时获取这个Token,然后使用这个Token进行登录。

后端处理确认登录的代码:

/** * 处理未待确认状态的二维码 * * @param code 二维码 * @param token token * @return 结果 */private BaseResult handleConfirmingQr(String code, String token) {    // 使用临时 token 获取用户名, 并从 redis 中删除临时 token    String username = redisCache.getCacheObject(token);    if (StringUtils.isBlank(username)) {        return BaseResult.error(AUTHENTICATION_FAILED);    }    redisCache.deleteObject(token);    // 根据用户名生成正式 token并保存在 redis 中供前端使用    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);}

效果演示

以上是"java中SpringBoot框架如何实现扫码登录"这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注行业资讯频道!

登录 二维 二维码 用户 状态 前端 生成 内容 信息 更新 手机 时间 用户名 结果 处理 有效 成功 选择 框架 操作系统 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 仁怀网络安全系统排行 计算机网络安全课程体会 网络安全宣传州简报 网络安全思科 婚贝请柬登陆显示连接服务器失败 电子信息是计算机网络技术吗 网络安全知识网络竞赛答案 校园网络安全工作重要批示 雅安软件开发 青岗科技 wincc项目服务器尚未运行 网络安全可以用u盘 中国材料数据库系统解决方案 买域名服务器 华为服务器管理员密码忘记 我的世界服务器逃离僵尸岛 邯郸应用软件开发多少钱 软件开发模型有哪些东西 中国医院网络安全工作 如何打开非数据库文件 简析对于网络安全的认识 计算机网络技术能报考二级吗 数据库有连接串该怎么连接 计算机网络技术对接本科学院 局域网哪个服务器好 重装系统网络安全模式 网络安全主题教育交流发言材料 sql查询数据库的表大小 广电网络技术部个人述职 武汉开立医疗软件开发岗待遇 将mysql服务器数据备份
0