django--通過jwt獲取用戶信息的兩種方式


HTTP請求是無狀態的,我們通常會使用cookie或session對其進行狀態保持,cookie存儲在客戶端,容易被用戶誤刪,安全性不高,session存儲在服務端,在服務器集群情況下需要解決session不共享的問題,常用的解決方案有4種:客戶端Cookie保存、服務器間Session同步、使用集群管理Session、把Session持久化到數據庫。

推薦:https://www.cnblogs.com/ruiati/p/6247588.html關於cookie和session的運行機制,以及四種解決session共享的對比介紹

jwt:json web token 

在用戶注冊登錄后,記錄用戶登錄狀態,我們可以用cookiesession來做狀態保持,cookie存儲在客戶端,安全性低,session存儲在服務器端,安全性高,但是在分布式架構中session不能同步化,所以我們用jwt來驗證接口安全

組成:頭部  載荷  簽證

Jwt服務端不需要存儲token串,用戶請求時攜帶着經過哈希加密和base64編碼后的字符串過來,服務端通過識別token值判斷用戶信息、過期時間等信息,在使用期間內不可能取消令牌或更改令牌權限。

 

jwt的安裝與配置

# 安裝 pip install djangorestframework-jwt
From rest_framework_jwt.authentication import JSONWebTokenAuthentication
Settings.py
INSTALLED_APPS = [
    '''
    'rest_framework.authtoken',  
    '''
]
################### 2、配置jwt驗證 ######################
REST_FRAMEWORK = {
    # 身份認證
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}
import datetime

JWT_AUTH = {
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
AUTH_USER_MODEL='app.User'  # 指定使用APP中的 model User進行驗證

 

 

在django中,我們用內置的User表做登錄功能

from rest_framework_jwt.views import obtain_jwt_token  # 驗證密碼后返回token

urlpatterns = [
    re_path(r'v1/login/$', obtain_jwt_token,name='login'),  # 用戶登錄后返回token
]

 

前端獲取到token並且setitem

var token = 'JWT ' + data.token
localStorage.setItem('token', token);

 

在我們封裝的攔截器里有請求攔截器和響應攔截器,需要在每次發起請求的時候獲取token
import Axios from 'axios'
import { Toast } from 'vant';
import URLS from '../../config/urls'

//1、使用自定義配置新建一個 axios 實例
const instance = Axios.create({
    baseURL: URLS.API_URL,
    responseType: 'json',
});

//2、添加請求攔截器:每次發送請求就會調用此攔截器,添加認證token
instance.interceptors.request.use(
    config => {
        //發送請求前添加認證token,
        console.log(localStorage.getItem('token'))
        config.headers.Authorization = localStorage.getItem('token');    # 獲取token
        // config.headers.Authorization = sessionStorage.getItem('token')
        return config
    },
    err => {
        return Promise.reject(err)
    });

// 3、響應攔截器
instance.interceptors.response.use(
    response => {
        if (response.status === 200) {
            return Promise.resolve(response);
        } else {
            return Promise.reject(response);
        }
    },
    // 服務器狀態碼不是200的情況
    error => {
        if (error.response.status) {
            switch (error.response.status) {
                // 401: 未登錄
                // 未登錄則跳轉登錄頁面,並攜帶當前頁面的路徑
                // 在登錄成功后返回當前頁面,這一步需要在登錄頁操作。
                case 401:
                    router.replace({
                        path: '/login',
                        query: { redirect: router.currentRoute.fullPath }
                    });
                    break;
                // 403 token過期
                // 登錄過期對用戶進行提示
                // 清除本地token和清空vuex中token對象
                // 跳轉登錄頁面
                case 403:
                    Toast({
                        message: '登錄過期,請重新登錄',
                        duration: 1000,
                        forbidClick: true
                    });
                    // 清除token
                    localStorage.removeItem('token');
                    store.commit('loginSuccess', null);
                    // 跳轉登錄頁面,並將要瀏覽的頁面fullPath傳過去,登錄成功后跳轉需要訪問的頁面
                    setTimeout(() => {
                        router.replace({
                            path: '/login',
                            query: {
                                redirect: router.currentRoute.fullPath
                            }
                        });
                    }, 1000);
                    break;
                // 404請求不存在
                case 404:
                    Toast({
                        message: '網絡請求不存在',
                        duration: 1500,
                        forbidClick: true
                    });
                    break;
                // 其他錯誤,直接拋出錯誤提示
                default:
                    Toast({
                        message: error.response.data.message,
                        duration: 1500,
                        forbidClick: true
                    });
            }
            return Promise.reject(error.response);
        }
    }
);

export default instance

  這樣即完成了jwt接口安全的認證

 

那么在python后端如何去獲取jwt並提取我們需要的信息呢?

from rest_framework_jwt.authentication import JSONWebTokenAuthentication 
from rest_framework.views import exception_handler
from rest_framework_jwt.utils import jwt_decode_handler
# 獲取登陸的用戶
        token = request.META.get('HTTP_AUTHORIZATION')[4:]
        token_user = jwt_decode_handler(token)
    
        user_id = token_user['user_id']  # 獲取用戶id
這個方法不用在前端封裝getitem token 



或者從前端傳過來token然后獲取
.vue
var formdata = {
                            id : this.$route.params.id,   //  獲取/id
                                   // this.$route.query.subid 獲取?subid=id
                            token: localStorage.getItem('token'),
                        }
                        postCreate(formdata).then(resp=>{
                            console.log(resp)
                            alert(resp.mes)
                        }).catch(err=>{
                            alert(err)
                            console.log(err)
                        })
                    }

python views.py
def post(self,request):
     data = request.data     # 獲取post方法的數據
        # print(data)
        token = data.get('token')[4:]
        toke_user = jwt_decode_handler(token)
        user_id = toke_user['user_id']   
def get(self,request):
    data = request.query_params # 獲取get方法的參數

 

 

 

OK!結束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM