欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

js實(shí)現(xiàn)無(wú)感刷新的實(shí)踐(附前后端實(shí)現(xiàn))

 更新時(shí)間:2024年04月09日 09:53:22   作者:接著奏樂接著舞。  
無(wú)感刷新機(jī)制的目的是在用戶不知情的情況下,自動(dòng)更新其認(rèn)證令牌本文,主要介紹了js實(shí)現(xiàn)無(wú)感刷新的實(shí)踐(附前后端實(shí)現(xiàn)),具有一定的參考價(jià)值,感興趣的可以了解一下

無(wú)感刷新的核心思路:

在這里插入圖片描述

無(wú)感刷新機(jī)制的目的是在用戶不知情的情況下,自動(dòng)更新其認(rèn)證令牌(通常是Access Token),以保證用戶的會(huì)話不會(huì)中斷。這通常涉及到兩種類型的令牌:

  • Access Token:它是用戶進(jìn)行認(rèn)證后得到的令牌,允許用戶訪問服務(wù)器的受保護(hù)資源。它有一個(gè)較短的有效期。

  • Refresh Token:它是在同一時(shí)間發(fā)放給用戶的另一個(gè)令牌,用于在Access Token過(guò)期時(shí)獲取一個(gè)新的Access Token。它的有效期比Access Token長(zhǎng)。

當(dāng)Access Token即將過(guò)期或已經(jīng)過(guò)期時(shí),客戶端會(huì)使用Refresh Token向認(rèn)證服務(wù)器請(qǐng)求一個(gè)新的Access Token。如果Refresh Token仍然有效,認(rèn)證服務(wù)器則發(fā)放一個(gè)新的Access Token給客戶端,并且可能會(huì)同時(shí)發(fā)放一個(gè)新的Refresh Token。這個(gè)過(guò)程對(duì)用戶來(lái)說(shuō)是沒有感知的,因此被稱為“無(wú)感”刷新。

在項(xiàng)目中實(shí)施無(wú)感刷新:

后端實(shí)施步驟:

認(rèn)證端點(diǎn)設(shè)置

  • 設(shè)計(jì)一個(gè)認(rèn)證API端點(diǎn),當(dāng)用戶初次登錄時(shí),返回Access Token和Refresh Token。
  • 設(shè)計(jì)一個(gè)Token刷新API端點(diǎn),只接受Refresh Token并返回新的Access Token(可選地返回新的Refresh Token)。

Token管理

  • Access Token應(yīng)有一個(gè)短暫的生命周期,例如15分鐘。
  • Refresh Token應(yīng)有一個(gè)長(zhǎng)期的生命周期,例如7天或更長(zhǎng),且應(yīng)該存儲(chǔ)在一個(gè)安全的存儲(chǔ)中。

安全考慮

  • 對(duì)Refresh Token進(jìn)行旋轉(zhuǎn)(每次使用后就廢棄舊的Refresh Token并發(fā)放一個(gè)新的)。
  • 通過(guò)HTTPS交換所有Token。
  • 應(yīng)用適當(dāng)?shù)募用艽胧﹣?lái)保護(hù)Token的安全。

前端實(shí)施步驟:

存儲(chǔ)Token

  • 在客戶端安全地存儲(chǔ)Access Token和Refresh Token(例如使用Web的localStorage或SecureStorage)。

攔截請(qǐng)求和響應(yīng)

  • 使用攔截器監(jiān)視所有出站請(qǐng)求和進(jìn)站響應(yīng)。
  • 在請(qǐng)求頭中自動(dòng)加入Access Token。

處理過(guò)期的Access Token

  • 當(dāng)接收到表示Token過(guò)期的HTTP狀態(tài)碼(例如401)時(shí),暫停發(fā)出的請(qǐng)求。
  • 使用Refresh Token請(qǐng)求新的Access Token。

處理新的Access Token

  • 更新存儲(chǔ)中的Access Token。
  • 重新發(fā)送之前因Token過(guò)期而暫停的請(qǐng)求。

處理Refresh Token過(guò)期

  • 如果Refresh Token也過(guò)期或無(wú)效,引導(dǎo)用戶重新登錄。

無(wú)感刷新機(jī)制的大概思路就是這些,下面是具體的示例,分為簡(jiǎn)化版和完整版,簡(jiǎn)化版目的是更好的了解無(wú)感刷新的原理,而完整版就要考慮一些其他問題,比如說(shuō)安全問題。

下面是實(shí)現(xiàn)無(wú)感刷新機(jī)制的具體示例(簡(jiǎn)化版)

這個(gè)例子涵蓋前端(使用JavaScript)和后端(Node.js環(huán)境下使用Express框架)

后端(Node.js/Express)

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const accessTokenSecret = 'YOUR_ACCESS_TOKEN_SECRET';
const refreshTokenSecret = 'YOUR_REFRESH_TOKEN_SECRET';
let refreshTokens = [];

app.post('/login', (req, res) => {
    // 用戶登錄邏輯,驗(yàn)證用戶憑證
    const { username, password } = req.body;

    // 這里應(yīng)該有邏輯來(lái)驗(yàn)證用戶憑證
    // 如果驗(yàn)證成功:
    const accessToken = jwt.sign({ username }, accessTokenSecret, { expiresIn: '15m' });
    const refreshToken = jwt.sign({ username }, refreshTokenSecret);
    refreshTokens.push(refreshToken);

    res.json({
        accessToken,
        refreshToken
    });
});

app.post('/refresh', (req, res) => {
    // 用戶發(fā)送refresh token來(lái)獲取新的access token
    const { refreshToken } = req.body;
    if (!refreshToken || !refreshTokens.includes(refreshToken)) {
        return res.sendStatus(403);
    }

    jwt.verify(refreshToken, refreshTokenSecret, (err, user) => {
        if (err) {
            return res.sendStatus(403);
        }

        const newAccessToken = jwt.sign({ username: user.username }, accessTokenSecret, { expiresIn: '15m' });

        res.json({
            accessToken: newAccessToken
        });
    });
});

app.listen(3000, () => {
    console.log('Authentication service started on port 3000');
});

前端(JavaScript/AJAX)

假設(shè)使用了axios作為HTTP客戶端,可以設(shè)置攔截器來(lái)自動(dòng)處理Token刷新。

axios.interceptors.response.use(response => {
    return response;
}, error => {
    const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
        originalRequest._retry = true;
        return axios.post('/refresh', {
            refreshToken: localStorage.getItem('refreshToken')
        }).then(res => {
            if (res.status === 200) {
                localStorage.setItem('accessToken', res.data.accessToken);
                axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('accessToken');
                return axios(originalRequest);
            }
        });
    }

    return Promise.reject(error);
});

這段代碼中,我們?cè)陧憫?yīng)攔截器中檢查任何錯(cuò)誤的響應(yīng)。如果我們得到一個(gè)401響應(yīng),并且這是第一次重試,我們就發(fā)送一個(gè)帶有refreshToken的請(qǐng)求到/refresh端點(diǎn)。如果刷新Token成功,我們就保存新的accessToken,更新請(qǐng)求頭,并重新發(fā)起失敗的請(qǐng)求。

完整示例

實(shí)現(xiàn)非簡(jiǎn)化的登錄無(wú)感刷新機(jī)制通常會(huì)涉及更詳細(xì)的認(rèn)證流程、錯(cuò)誤處理、日志記錄和安全性措施。這包括使用數(shù)據(jù)庫(kù)存儲(chǔ)Refresh Tokens、自動(dòng)撤銷機(jī)制、雙因素認(rèn)證等。

后端實(shí)現(xiàn)(Node.js/Express + MongoDB)

首先,你需要設(shè)置一個(gè)數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)Refresh Tokens。出于安全考慮,每個(gè)Refresh Token都應(yīng)該與一個(gè)用戶賬戶關(guān)聯(lián),并且能夠被追蹤和撤銷。

const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const User = require('./models/User'); // 導(dǎo)入U(xiǎn)ser模型
const RefreshToken = require('./models/RefreshToken'); // 導(dǎo)入RefreshToken模型
const app = express();

// ...其他必要的中間件和數(shù)據(jù)庫(kù)連接代碼...

app.post('/login', async (req, res) => {
    // 用戶登錄邏輯,驗(yàn)證用戶憑證
    const { username, password } = req.body;
    const user = await User.findOne({ username });

    if (user && bcrypt.compareSync(password, user.password)) {
        const accessToken = jwt.sign({ userId: user._id }, accessTokenSecret, { expiresIn: '15m' });
        const refreshToken = jwt.sign({ userId: user._id }, refreshTokenSecret);

        // 保存refresh token到數(shù)據(jù)庫(kù)
        const newRefreshToken = new RefreshToken({ token: refreshToken, user: user._id });
        await newRefreshToken.save();

        res.json({ accessToken, refreshToken });
    } else {
        res.status(401).send('Username or password incorrect');
    }
});

app.post('/refresh', async (req, res) => {
    // 用戶發(fā)送refresh token來(lái)獲取新的access token
    const { refreshToken } = req.body;
    const dbToken = await RefreshToken.findOne({ token: refreshToken });

    if (!dbToken) {
        return res.status(403).send('Refresh token not found');
    }

    jwt.verify(refreshToken, refreshTokenSecret, async (err, decoded) => {
        if (err) {
            return res.status(403).send('Refresh token invalid');
        }

        // 生成新的access token和refresh token
        const newAccessToken = jwt.sign({ userId: decoded.userId }, accessTokenSecret, { expiresIn: '15m' });
        const newRefreshToken = jwt.sign({ userId: decoded.userId }, refreshTokenSecret);

        // 更新數(shù)據(jù)庫(kù)中的refresh token
        dbToken.token = newRefreshToken;
        await dbToken.save();

        res.json({ accessToken: newAccessToken, refreshToken: newRefreshToken });
    });
});

app.listen(3000, () => {
    console.log('Authentication service started on port 3000');
});

在此示例中,我們使用了MongoDB來(lái)存儲(chǔ)用戶和他們的Refresh Tokens。登錄時(shí),我們驗(yàn)證用戶憑證,并且如果認(rèn)證成功,我們就生成Access Token和Refresh Token,然后將Refresh Token保存到數(shù)據(jù)庫(kù)。在無(wú)感刷新流程中,我們驗(yàn)證提供的Refresh Token是否存在于數(shù)據(jù)庫(kù)中,并且是否有效,然后發(fā)放新的Access Token。

前端實(shí)現(xiàn)(JavaScript/AJAX + Local Storage)

在前端實(shí)現(xiàn)中,我們需要確保存儲(chǔ)Token的方法是安全的。在生產(chǎn)環(huán)境中,你可能需要考慮使用更安全的存儲(chǔ)方式,如HTTPOnly Cookies或Secure Local Storage。

axios.interceptors.response.use(
  response => response,
  error => {
    const originalRequest = error.config;

    // 檢測(cè)token過(guò)期的錯(cuò)誤代碼,比如401
    if (error.response.status === 401 && originalRequest.url === '/refresh') {
      // 刷新Token失敗,直接登出用戶
      logoutUser();
      return Promise.reject(error);
    }

    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      return axios.post('/refresh', { refreshToken: localStorage.getItem('refreshToken') })
        .then(res => {
          if (res.status === 200) {
            // 將新token設(shè)置到本地存儲(chǔ)和axios默認(rèn)頭部
            localStorage.setItem('accessToken', res.data.accessToken);
            localStorage.setItem('refreshToken', res.data.refreshToken);
            axios.defaults.headers.common['Authorization'] = 'Bearer ' + res.data.accessToken;

            // 更新失敗請(qǐng)求的頭部并重新發(fā)送


            originalRequest.headers['Authorization'] = 'Bearer ' + res.data.accessToken;
            return axios(originalRequest);
          }
        })
        .catch(error => {
          // 任何錯(cuò)誤都直接登出用戶
          logoutUser();
          return Promise.reject(error);
        });
    }

    return Promise.reject(error);
  }
);

function logoutUser() {
  // 清除本地存儲(chǔ)和狀態(tài),重定向到登錄頁(yè)面
  localStorage.removeItem('accessToken');
  localStorage.removeItem('refreshToken');
  // ...重定向到登錄頁(yè)的代碼...
}

在前端的實(shí)現(xiàn)中,我們創(chuàng)建了一個(gè)axios攔截器,它會(huì)在遇到401未授權(quán)的響應(yīng)時(shí)自動(dòng)嘗試刷新Token。如果刷新Token請(qǐng)求也失敗,則觸發(fā)用戶登出的邏輯。

注意:此功能一定要注意其安全性,具體的話要結(jié)合實(shí)際的項(xiàng)目,以下是我的一些建議:
安全方面通常包括以下幾個(gè)方法:

1. 使用HTTPS來(lái)加密所有的通信。

2. 安全地存儲(chǔ)Access Token和Refresh Token,如使用httpOnly和Secure屬性的Cookies。

3. 對(duì)Token進(jìn)行定期輪換,特別是Refresh Token。

4. 在服務(wù)器端驗(yàn)證Token的簽名。

5. 設(shè)置適當(dāng)?shù)腡oken過(guò)期時(shí)間。

6. 實(shí)現(xiàn)Token撤銷邏輯,以便在檢測(cè)到異常時(shí)能夠立即廢棄使用。

7. 避免在客戶端暴露敏感的認(rèn)證邏輯。

8. 對(duì)所有的認(rèn)證請(qǐng)求和Token刷新請(qǐng)求進(jìn)行率限制和異常監(jiān)測(cè)。

9. 使用跨站請(qǐng)求偽造(CSRF)保護(hù)措施。

10. 確??蛻舳撕头?wù)端都有充分的錯(cuò)誤處理和日志記錄機(jī)制。

到此這篇關(guān)于js實(shí)現(xiàn)無(wú)感刷新的實(shí)踐(附前后端實(shí)現(xiàn))的文章就介紹到這了,更多相關(guān)js 無(wú)感刷新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序?qū)崿F(xiàn)簡(jiǎn)單的計(jì)算器功能

    微信小程序?qū)崿F(xiàn)簡(jiǎn)單的計(jì)算器功能

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)簡(jiǎn)單的計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • ES6新特性之變量和字符串用法示例

    ES6新特性之變量和字符串用法示例

    這篇文章主要介紹了ES6新特性之變量和字符串用法,結(jié)合具體實(shí)例形式分析了ES6中變量與字符串的特性、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-04-04
  • JS簡(jiǎn)單隨機(jī)數(shù)生成方法

    JS簡(jiǎn)單隨機(jī)數(shù)生成方法

    這篇文章主要介紹了JS簡(jiǎn)單隨機(jī)數(shù)生成方法,通過(guò)javascript自定義函數(shù)演示了隨機(jī)數(shù)的生成方法,需要的朋友可以參考下
    2016-09-09
  • 原生JS檢測(cè)CSS3動(dòng)畫是否結(jié)束的方法詳解

    原生JS檢測(cè)CSS3動(dòng)畫是否結(jié)束的方法詳解

    這篇文章主要介紹了原生JS檢測(cè)CSS3動(dòng)畫是否結(jié)束的方法,結(jié)合實(shí)例形式分析了javascript事件響應(yīng)及針對(duì)css3屬性檢測(cè)相關(guān)操作技巧,需要的朋友可以參考下
    2019-01-01
  • JS前端開發(fā)模擬虛擬dom轉(zhuǎn)真實(shí)dom詳解

    JS前端開發(fā)模擬虛擬dom轉(zhuǎn)真實(shí)dom詳解

    這篇文章主要為大家介紹了JS前端開發(fā)模擬虛擬dom轉(zhuǎn)真實(shí)dom詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • JS FormData上傳文件的設(shè)置方法

    JS FormData上傳文件的設(shè)置方法

    使用FormData上傳文件時(shí),總是獲取不到req.file對(duì)象。發(fā)現(xiàn)是沒有配置對(duì)FormData導(dǎo)致的,怎么解決這個(gè)問題呢?下面小編給大家?guī)?lái)了JS FormData上傳文件的設(shè)置方法,需要的朋友參考下吧
    2017-07-07
  • JS實(shí)現(xiàn)的簡(jiǎn)單拖拽功能示例

    JS實(shí)現(xiàn)的簡(jiǎn)單拖拽功能示例

    這篇文章主要介紹了JS實(shí)現(xiàn)的簡(jiǎn)單拖拽功能,涉及javascript鼠標(biāo)事件響應(yīng)及頁(yè)面元素屬性動(dòng)態(tài)操作相關(guān)技巧,需要的朋友可以參考下
    2017-03-03
  • js數(shù)字計(jì)算 誤差問題的快速解決方法

    js數(shù)字計(jì)算 誤差問題的快速解決方法

    下面小編就為大家?guī)?lái)一篇js數(shù)字計(jì)算 誤差問題的快速解決方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-02-02
  • js實(shí)現(xiàn)的點(diǎn)擊超鏈顯示隱藏層

    js實(shí)現(xiàn)的點(diǎn)擊超鏈顯示隱藏層

    js實(shí)現(xiàn)的點(diǎn)擊超鏈顯示隱藏層...
    2007-05-05
  • 使用pcs api往免費(fèi)的百度網(wǎng)盤上傳下載文件的方法

    使用pcs api往免費(fèi)的百度網(wǎng)盤上傳下載文件的方法

    百度個(gè)人云盤空間大,完全免費(fèi),而且提供了pcs api供調(diào)用操作文件,在平時(shí)的項(xiàng)目里往里面保存一些文件是很實(shí)用的。通過(guò)本文給大家介紹使用pcs api往免費(fèi)的百度網(wǎng)盤上傳下載文件的方法,感興趣的朋友一起學(xué)習(xí)吧
    2016-03-03

最新評(píng)論