首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JWT无状态的真正含义是什么?

JWT无状态的真正含义是什么?
EN

Stack Overflow用户
提问于 2021-02-03 22:38:30
回答 1查看 99关注 0票数 2

嗨,提前谢谢你,

我已经使用django-rest-framework-simplejwt和React成功地设置了JWT身份验证,但我仍然对其优点以及具体的数据库命中感到困惑。我在ROTATE_REFRESH_TOKENS': True 'BLACKLIST_AFTER_ROTATION': True中使用simplejwt,当我的令牌到期时,我通过/api/ access_token /refresh请求一个新的令牌,它将旧的令牌列入黑名单,我使用axios拦截器自动执行这一操作。

但在我的理解中,JWt的好处是它们是无状态的,这意味着每次我想发出需要身份验证权限的请求时,都不必访问用户数据库表。即使是这样一个简单的视图,问题仍然存在:

代码语言:javascript
复制
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代码:

代码语言:javascript
复制
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,但无所谓)

我通常只会调用这个函数来向上面编写的视图发出简单的请求:

代码语言:javascript
复制
 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);
      });
  };
EN

回答 1

Stack Overflow用户

发布于 2021-02-03 23:19:47

如果没有确切的查询命中数据库的细节,就很难判断发生了什么(数据库查询一定来自中间件,因为您的代码中没有执行该查询的内容,我怀疑它是django的CsrfViewMiddleware)。然而,对于你的JWT是无状态的问题,我建议你看看官方的introduction

基本上,JWT的作用是您的服务器使用服务器的密钥对令牌执行签名验证(请注意某些problems)。如果验证通过,那么存储在JWT中的数据是可信的,并按原样读取,这就是为什么不需要数据库查询的原因。当然,这确实意味着您的用户将确切地知道他们的令牌中存储了什么,因为数据是一个简单的base64编码的JSON对象。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66029725

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档