嗨,提前谢谢你,
我已经使用django-rest-framework-simplejwt和React成功地设置了JWT身份验证,但我仍然对其优点以及具体的数据库命中感到困惑。我在ROTATE_REFRESH_TOKENS': True 'BLACKLIST_AFTER_ROTATION': True中使用simplejwt,当我的令牌到期时,我通过/api/ access_token /refresh请求一个新的令牌,它将旧的令牌列入黑名单,我使用axios拦截器自动执行这一操作。
但在我的理解中,JWt的好处是它们是无状态的,这意味着每次我想发出需要身份验证权限的请求时,都不必访问用户数据库表。即使是这样一个简单的视图,问题仍然存在:
class IsConnecteddAPI(APIView):
permission_classes = [permissions.IsAuthenticated]
def get(self, request, *args, **kwargs):
data = "You seem to be connected"
return Response(data, status=status.HTTP_200_OK)使用django-silk我发现,当我使用有效的访问令牌调用它时,它仍然对我的用户表执行1次查询,这正常吗?如果是这样,为什么我们说JWT是无状态的?我真的很困惑。
如果需要,这是我的axios代码:
import axios from "axios";
const baseURL = "http://localhost:5000";
const axiosInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
headers: {
Authorization: localStorage.getItem("accesstoken")
? "JWT " + localStorage.getItem("accesstoken")
: null,
"Content-Type": "application/json",
accept: "application/json",
},
});
const axioAnonymousInstance = axios.create({
baseURL: baseURL,
timeout: 5000,
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
});
axiosInstance.interceptors.response.use(
(response) => {
return response;
},
async function (error) {
const originalRequest = error.config;
if (typeof error.response === "undefined") {
alert(
"A server/network error occurred. " +
"Looks like CORS might be the problem. " +
"Sorry about this - we will get it fixed shortly."
);
return Promise.reject(error);
}
if (
error.response.status === 401 &&
originalRequest.url === baseURL + "token/refresh/"
) {
window.location.href = "/login/";
return Promise.reject(error);
}
if (
error.response.data.code === "token_not_valid" &&
error.response.status === 401 &&
error.response.statusText === "Unauthorized"
) {
const refreshToken = localStorage.getItem("refreshtoken");
if (refreshToken) {
const tokenParts = JSON.parse(atob(refreshToken.split(".")[1]));
// exp date in token is expressed in seconds, while now() returns milliseconds:
const now = Math.ceil(Date.now() / 1000);
console.log(tokenParts.exp);
if (tokenParts.exp > now) {
return axioAnonymousInstance
.post("/api/token/refresh/", { refresh: refreshToken })
.then((response) => {
localStorage.setItem("accesstoken", response.data.access);
localStorage.setItem("refreshtoken", response.data.refresh);
axiosInstance.defaults.headers["Authorization"] =
"JWT " + response.data.access;
originalRequest.headers["Authorization"] =
"JWT " + response.data.access;
return axiosInstance(originalRequest);
})
.catch((err) => {
// redirect ro /login here if wanted
console.log("axios Safe Instance error");
console.log(err);
// window.location.href = "/login/";
});
} else {
console.log("Refresh token is expired", tokenParts.exp, now);
window.location.href = "/login/";
}
} else {
console.log("Refresh token not available.");
window.location.href = "/login/";
}
}
// specific error handling done elsewhere
return Promise.reject(error);
}
);
export { axiosInstance, axioAnonymousInstance };(我知道我不应该使用localStorage,但无所谓)
我通常只会调用这个函数来向上面编写的视图发出简单的请求:
const IsConnected = () => {
axiosInstance
.get("/api/is_connected/")
.then((response) => {
if (response.status === 200) {
console.log(response.data);
console.log("Is connected : CONNECTED ");
} else {
console.log("IS connected : not connected");
}
})
.catch((error) => {
console.log("Is connected : NOT CONNECTED");
console.log(error);
});
};发布于 2021-02-03 23:19:47
如果没有确切的查询命中数据库的细节,就很难判断发生了什么(数据库查询一定来自中间件,因为您的代码中没有执行该查询的内容,我怀疑它是django的CsrfViewMiddleware)。然而,对于你的JWT是无状态的问题,我建议你看看官方的introduction。
基本上,JWT的作用是您的服务器使用服务器的密钥对令牌执行签名验证(请注意某些problems)。如果验证通过,那么存储在JWT中的数据是可信的,并按原样读取,这就是为什么不需要数据库查询的原因。当然,这确实意味着您的用户将确切地知道他们的令牌中存储了什么,因为数据是一个简单的base64编码的JSON对象。
https://stackoverflow.com/questions/66029725
复制相似问题