【发布时间】:2021-09-14 05:41:57
【问题描述】:
我正在使用 JWT 令牌来验证我的 API 请求。访问令牌在 1 分钟后过期,刷新令牌在 1 年内过期。访问令牌过期后,会发送一个带有刷新令牌的 API 请求以获取一组新令牌。仅当刷新令牌有效且存在于数据库中时才会发送一组新令牌。我正在使用 Axios 拦截器来实现这一点。一段时间以来,一切似乎都可以正常工作。但是,即使刷新令牌有效并且数据库中确实存在,它也会将我注销。我假设我在 Axios 拦截器中遗漏了一些东西,或者与异步函数有关。
服务器端verifyRefreshToken函数中的错误日志“代码不匹配”,客户端updateToken函数中的“此处错误”。
客户端代码 API.js
// Response interceptor for API calls
API.interceptors.response.use((response) => {
return response
}, async (error) => {
// reject promise if network error
if (!error.response) {
console.log("Network Error");
return Promise.reject(error);
}
const originalRequest = error.config;
console.log(store.getState().auth)
// if access token is expired
if (error.response.status === 403 && error.response.data.message == "token expired") {
// var refreshToken = await getRefreshToken() // get refresh token from local storage
var refreshToken = await store.getState().auth.refreshToken
// restore tokens using refresh token
await store.dispatch(await updateToken(refreshToken)) // get new set of tokens from server and store tokens in redux state
// var newAccessToken = await getToken() // get token from local storage
var newAccessToken = await store.getState().auth.accessToken
if(newAccessToken != null){
originalRequest.headers["Authorization"] = `Bearer ${newAccessToken}`;
return API(originalRequest)
}
return Promise.reject(error);
}
// if refresh token is expired or does not match
if (error.response.status === 403 && error.response.data.message == "false token") {
socketDisconnect() // disconnect socket connection
signOut() // remove tokens from local storage
store.dispatch(logOut()) // set tokens in redux as null
return Promise.reject(error);
}
return Promise.reject(error);
});
更新令牌函数
export const updateToken = (rt) => {
return async (dispatch) => {
const data = await API.post('/auth/refreshToken', {
token: rt
})
.then(async res => {
var accessToken = res.data.accessToken
var refreshToken = res.data.refreshToken
await storeToken(accessToken) // store access token in local storage
await storeRefreshToken(refreshToken) // store refresh token in local storage
dispatch(restoreToken({accessToken, refreshToken})) // store token in redux state
})
.catch(err => {
console.log("err here" + err) // LOG SHOWS ERROR HERE
})
}
}
服务器端代码 // /auth/refreshToken
// POST: /api/auth/refreshToken
router.post('/', (req, res) => {
var { token } = req.body
if(!token) res.status(403).send({"status":false, "message": "false token", "result": ""})
verifyRefreshToken(token)
.then(async data => {
var userName = data.userName
// get new tokens
var accessToken = await getAccessToken(userName)
var refreshToken = await getRefreshToken(userName)
res.json({"status":true, "message": "token verified", "accessToken": accessToken, "refreshToken": refreshToken})
})
.catch(err => {
console.log(err);
res.status(403).send({"status":false, "message": "false token", "result": ""})
})
});
生成新的刷新令牌
// generate refresh token
const getRefreshToken = (userName) => {
return new Promise((resolve, reject) => {
var secret = process.env.REFRESH_TOKEN_SECRET
var options = { expiresIn: '1y' }
jwt.sign({userName},secret , options, (err, token) => {
if(err) reject("error")
var data = {"userName": userName, "token": token}
// delete all expired token from database
dbQueries.deleteRefreshToken(data, result => {
})
// add refresh token to database
dbQueries.addRefreshToken(data, result => {
if(result == "success"){
console.log("added token " + token);
resolve(token)
}else{
reject("failure")
}
})
});
})
}
验证刷新令牌
// verify access token
const verifyRefreshToken = (token) => {
return new Promise((resolve, reject) => {
var secret = process.env.REFRESH_TOKEN_SECRET
if(!token) return reject("no token")
jwt.verify(token, secret, (err, user) => {
if(err){
return reject(err)
}
// check if the verified token and token from database matches
var data = {"userName": user.userName}
dbQueries.getRefreshToken(data, result => {
if(result.length == 0){
return reject("no data")
}
if(token === result[0].token){
resolve(user)
} else{
reject("code does not match") // LOGS THIS ERROR
}
})
})
})
}
【问题讨论】:
标签: javascript node.js reactjs react-native jwt