drf中jwt应用

第一步  在登录类中生成 jwt

class Login(MyException,APIView):
    def post(self,request):
        user_obj = models.UserInfo.objects.filter(**request.data).first()
        if not user_obj:
            return Response({"code":1001, "msg":"用户名密码错误"})
        # 生成jwt token并返回
        headers = {
            'typ': 'jwt',
            'alg': 'HS256'
        }
        # 构造payload
        payload = {
            'user_id': user_obj.id,  # 自定义用户ID
            'username': user_obj.username,  # 自定义用户名
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5)  # 超时时间
        }
        token = jwt.encode(payload=payload, key=settings.SECRET_KEY, algorithm="HS256", headers=headers)
        print("t:",token)
        return Response({"code":0, "msg":"登录成功", "token":token,"username":user_obj.username,"userid":user_obj.id})

第二步 在认证类中校验 jwt合法性

  

class TestAuthentication(BaseAuthentication):
def authenticate(self, request):
    token = request.query_params.get("token")
    if not token:
        raise AuthenticationFailed({"code":1002,"msg":"必须携带token"})
    # 2.合法性
    try:
        # print(token)
        verified_payload = jwt.decode(token, settings.SECRET_KEY, algorithms="HS256")
        print("v:",verified_payload)
        current_timestamp = int(datetime.datetime.now().timestamp())
        print(current_timestamp)
        print(verified_payload.get("exp"))
        #判断是否需要更新jwt
        verified_payload["exp_time"] = verified_payload.get("exp") - current_timestamp
        # 获取当前时间 vs 有效期
        return (verified_payload, token)
    except Exception as e:
        print(e)
        raise AuthenticationFailed("认证失败")

 

第三步 写一个更新jwt的类

class UpdateTokenView(ResView,APIView):
    authentication_classes = [MyAuthentication]

    def get(self, request):
        print("info:",request.user, request.auth)
        # 生成jwt token并返回
        headers = {
            'typ': 'jwt',
            'alg': 'HS256'
        }
        # 构造payload
        payload = {
            'user_id': request.user['user_id'],  # 自定义用户ID
            'username': request.user['username'],  # 自定义用户名
            'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5)  # 超时时间
        }
        token = jwt.encode(payload=payload, key=settings.SECRET_KEY, algorithm="HS256", headers=headers)
        return Response(token)

第四步 在统一返回格式处,添加过期字段

class ResView:
    def finalize_response(self, request, response, *args, **kwargs):
        response = super().finalize_response(request, response, *args, **kwargs)
        if response.exception:
            return response
        response.data = {"code": 0, "data": response.data,"exp_time": request.user.get("exp_time")}
        return response

第五步 添加url

    path('api/jwt/update/', views.UpdateTokenView.as_view()),

第六步 前端部分 在 store中创建一个更新用户信息中token的函数

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'

export const userInfoStore = defineStore('userInfo', () => {

    const userString = ref(localStorage.getItem("info"))
    const userDict = computed(() => userString.value ? JSON.parse(userString.value) : null)
    const userId = computed(() => userDict.value ? userDict.value.id : null)
    const userName = computed(() => userDict.value ? userDict.value.username : null)
    const userToken = computed(() => userDict.value ? userDict.value.token : null)


    function doLogin(info) {
      localStorage.setItem("info",JSON.stringify(info));
      userString.value = JSON.stringify(info)
    }


    function Logout(){
      localStorage.clear()
    }

    function updateUserInfo(new_token) {
      const userInfoObject = JSON.parse(userString.value);
      userInfoObject.token = new_token;
      localStorage.setItem("info",JSON.stringify(userInfoObject));
      userString.value = JSON.stringify(userInfoObject)
  }

    return {userDict,userId,userName,userToken,doLogin,Logout,updateUserInfo }
})

第七步 判断返回的数据中 过期时间字段,如果即将过期,就再发起一次更新token的操作

    onMounted(function getdata(){
    elLoading.value = true
    _axios.get("/api/project/").then(
        (res) =>{
            console.log("res.data:",res.data.data)
            console.log("res.data.count:",res.data.data.count)
            console.log("res.data.results.len:",res.data.data.page_size)
            console.log("res.data.exp:",res.data.exp_time)
            if (res.data.exp_time > 0 && res.data.exp_time < 30 ) {
                console.log("需要去更新token")
                _axios.get("/api/jwt/update/").then(
                    (res) =>{
                        console.log(res.data.data)
                        let new_token = res.data.data
                        userdata.updateUserInfo(new_token)
                    }
                )
            }
            response.value = res.data.data.results
            elLoading.value = false
            // 返回数据总数和每页条数
            page.value = {
                count:res.data.data.count,
                page_size:res.data.data.page_size
            }

        }
    ).catch((reson) => {
        console.log("reson:",reson)
    })
    })

 

posted @ 2024-04-22 15:49  李瑞鑫  阅读(20)  评论(0编辑  收藏  举报