問題描述
注意:我已經分離了我的客戶端(Vue.js)和服務器(DjangoRest).我正在使用 JWT 驗證從客戶端向服務器發出的每個請求.流動-客戶端將用戶憑據發送到服務器.如果憑據有效,服務器會發回刷新和訪問令牌.客戶端存儲訪問和刷新令牌.我已將刷新令牌到期時間設置為 1 周,訪問時間為 30 分鐘.接下來,我想確保訪問令牌在到期前 15 分鐘自動刷新.為此,將存儲在客戶端的刷新令牌發送到服務器,然后服務器發出新的訪問令牌和刷新令牌,將其發送回客戶端.我如何在 Vuex 商店中實現這一點?我是 web 開發和 vue.js 的新手.如果有人能提供一些代碼或詳細解釋,那就太好了.
Note: I have seperated my client(Vue.js) and server(DjangoRest). I'm using JWT to validate every request made from the client to the server. Flow- Client sends user credentials to server. Server sends back a refresh and access token if credentials are valid. Client stores the access and refresh token. I have set the refresh token expiry to 1 week,access to 30 mins. Next, I want to make sure that the access token is auto refreshed 15 mins prior to its expiry. To do this, the stored refresh token in client side is send to the server, the server then issues a new access token and refresh token, sends it back to the client. How do i implement this in the Vuex store?. I'm a complete newbie to web development and vue.js. It would be great if someone could provide some code or explain in details.
我已經在商店中實現了 loginUser、logout user、registerUser 并且它們工作正常.但我堅持使用自動刷新邏輯.我的猜測是客戶端必須反復檢查剩余的訪問令牌到期時間.剩下大約 15 分鐘時,我們必須初始化自動刷新功能.請幫我解決這個邏輯.
I have already implemented loginUser,logout user,registerUser in store and they are working fine. But I'm stuck with the auto refresh logic. My guess is that the client has to repeatedly check the access token expiry time left. When about 15 mins is left, we have to initialize the autorefresh function. Please help me with this logic.
這是我的 Vueex 商店:
Here's my Vueex store:
import Vue from 'vue'
import Vuex from 'vuex'
import axiosBase from './api/axios-base'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
accessToken: '' || null,
refreshToken: '' || null
},
getters: {
loggedIn (state) {
return state.accessToken != null
}
},
mutations: {
loginUser (state) {
state.accessToken = localStorage.getItem('access_token')
state.refreshToken = localStorage.getItem('refresh_token')
},
destroyToken (state) {
state.accessToken = null
state.refreshToken = null
}
},
actions: {
registerUser (context, data) {
return new Promise((resolve, reject) => {
this.axios.post('/register', {
name: data.name,
email: data.email,
username: data.username,
password: data.password,
confirm: data.confirm
})
.then(response => {
resolve(response)
})
.catch(error => {
reject(error)
})
})
},
// fetch data from api whenever required.
backendAPI (context, data) {
},
logoutUser (context) {
if (context.getters.loggedIn) {
return new Promise((resolve, reject) => {
axiosBase.post('/api/token/logout/')
.then(response => {
localStorage.removeItem('access_token')
localStorage.removeItem('refresh_token')
context.commit('destroyToken')
})
.catch(error => {
context.commit('destroyToken')
resolve()
})
})
}
},
autoRefresh (context, credentials) {
},
loginUser (context, credentials) {
return new Promise((resolve, reject) => {
axiosBase.post('/api/token/', {
username: credentials.username,
password: credentials.password
})
.then(response => {
localStorage.setItem('access_token', response.data.access)
localStorage.setItem('refresh_token', response.data.refresh)
context.commit('loginUser')
resolve(response)
})
.catch(error => {
console.log(error)
reject(error)
})
})
}
}
})
提前謝謝你.
推薦答案
正如您所指出的,這是一個非常有創意的問題,因此有很多解決方法.
This is very much an idea question as you've pointed out and as such, there are many ways of solving it.
在處理此類機制時,我要記住的一件事是盡可能避免輪詢.這是一個受該設計原則啟發的解決方案.
One thing I try to keep in mind when dealing with such mechanisms is to always avoid polling when possible. Here's a solution inspired by that design principle.
JWT 令牌在非常特定的時間內有效.作為訪問令牌的一部分,剩余的到期時間很容易獲得.您可以使用諸如 jwt-decode 之類的庫來解碼訪問令牌并提取到期時間.設置到期時間后,您有多種選擇:
JWT tokens are valid for a very specific amount of time. The time left for expiration is readily available as part of the access token. You can use a library such as jwt-decode to decode the access token and extract the expiration time. Once you have the expiration time, you have a several options available:
- 每次發出請求前檢查令牌以了解是否需要刷新
- 使用
setTimeout
在過期前 X 秒定期刷新
- Check token every time before making a request to know if it needs to be refreshed
- Use
setTimeout
to refresh it periodically X seconds before it expires
您的代碼可以實現如下:
注意:請將以下內容視為偽代碼.我沒有測試它是否有錯誤——語法或其他.
Your code could be implemented as follows:
Note: Please treat the following as pseudo-code. I have not tested it for errors---syntax or otherwise.
export default new Vuex.Store({
...
actions: {
refreshTokens (context, credentials) {
// Do whatever you need to do to exchange refresh token for access token
...
// Finally, call autoRefresh to set up the new timeout
dispatch('autoRefresh', credentials)
},
autoRefresh (context, credentials) {
const { state, commit, dispatch } = context
const { accessToken } = state
const { exp } = jwt_decode(accessToken)
const now = Date.now() / 1000 // exp is represented in seconds since epoch
let timeUntilRefresh = exp - now
timeUntilRefresh -= (15 * 60) // Refresh 15 minutes before it expires
const refreshTask = setTimeout(() => dispatch('refreshTokens', credentials), timeUntilRefresh * 1000)
commit('refreshTask', refreshTask) // In case you want to cancel this task on logout
}
}
})
這篇關于如何在客戶端(vue.js)實現自動刷新?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!