中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java中SpringBoot框架如何實現掃碼登錄

發布時間:2021-09-24 11:01:04 來源:億速云 閱讀:311 作者:小新 欄目:開發技術

這篇文章主要介紹java中SpringBoot框架如何實現掃碼登錄,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

項目簡介

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

實現思路

總體的掃碼登錄和OAuth3.0的驗證邏輯相似,如下所示:

java中SpringBoot框架如何實現掃碼登錄

用戶選擇掃碼登錄可以看作是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框架如何實現掃碼登錄

java中SpringBoot框架如何實現掃碼登錄

以上是“java中SpringBoot框架如何實現掃碼登錄”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

秦皇岛市| 定陶县| 普安县| 兴义市| 黄冈市| 玉溪市| 呼伦贝尔市| 贵定县| 杂多县| 额敏县| 彭州市| 荥阳市| 保亭| 安龙县| 阳高县| 河北区| 盐亭县| 宁国市| 阿鲁科尔沁旗| 高淳县| 稷山县| 西贡区| 东乡族自治县| 丹阳市| 开远市| 阳原县| 饶阳县| 思茅市| 仁布县| 衡南县| 南郑县| 静宁县| 吉水县| 泰和县| 哈巴河县| 岐山县| 长岛县| 睢宁县| 望城县| 浙江省| 郓城县|