亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vue?和?Django?實(shí)現(xiàn)?Token?身份驗(yàn)證的流程

 更新時(shí)間:2022年08月18日 10:44:19   作者:ZewanHuang  
這篇文章主要介紹了Vue?和?Django?實(shí)現(xiàn)?Token?身份驗(yàn)證?,Vue.js?和?Django?編寫(xiě)的前后端項(xiàng)目中,實(shí)現(xiàn)了基于?Token?的身份驗(yàn)證機(jī)制,其他前后端框架的?Token?實(shí)現(xiàn)原理與本文一致,需要的朋友可以參考下

使用 Django 編寫(xiě)的 B/S 應(yīng)用通常會(huì)使用 Cookie + Session 的方式來(lái)做身份驗(yàn)證,用戶(hù)登錄信息存儲(chǔ)在后臺(tái)數(shù)據(jù)庫(kù)中,前端 Cookie 也會(huì)存儲(chǔ)少量用于身份核驗(yàn)的數(shù)據(jù),由后臺(tái)直接寫(xiě)入。但是在開(kāi)發(fā)調(diào)試階段,使用 Postman 等請(qǐng)求工具請(qǐng)求登錄時(shí),可能會(huì)缺失前端本應(yīng)存儲(chǔ)的數(shù)據(jù),而導(dǎo)致登錄信息核驗(yàn)一直不成功。本篇介紹基于 Token 的身份驗(yàn)證機(jī)制,并使用 Vue 和 Django 實(shí)現(xiàn)。

使用 Django 編寫(xiě)的 B/S 應(yīng)用通常會(huì)使用 Cookie + Session 的方式來(lái)做身份驗(yàn)證,用戶(hù)登錄信息存儲(chǔ)在后臺(tái)數(shù)據(jù)庫(kù)中,前端 Cookie 也會(huì)存儲(chǔ)少量用于身份核驗(yàn)的數(shù)據(jù),由后臺(tái)直接寫(xiě)入。但是在開(kāi)發(fā)調(diào)試階段,使用 Postman 等請(qǐng)求工具請(qǐng)求登錄時(shí),可能會(huì)缺失前端本應(yīng)存儲(chǔ)的數(shù)據(jù),而導(dǎo)致登錄信息核驗(yàn)一直不成功。在本地聯(lián)調(diào)前后端時(shí)可能也會(huì)有問(wèn)題。

本篇介紹基于 Token 的身份驗(yàn)證機(jī)制,并使用 Vue 和 Django 實(shí)現(xiàn)。

基于 Token 的驗(yàn)證流程

與 Session 不同的是,Token 機(jī)制不會(huì)將用戶(hù)登錄信息存儲(chǔ)在后臺(tái)數(shù)據(jù)庫(kù)中,而是生成含有身份信息的 Token 字符串存儲(chǔ)在前端中。在前端請(qǐng)求需要驗(yàn)證的后臺(tái) API 時(shí),后端將優(yōu)先攔截并核驗(yàn)身份信息。

基于 Token 的驗(yàn)證流程如下:

  • 客戶(hù)端使用用戶(hù)名和密碼請(qǐng)求登錄
  • 服務(wù)器收到請(qǐng)求后,驗(yàn)證用戶(hù)名和密碼
  • 驗(yàn)證成功后,服務(wù)端根據(jù)用戶(hù)信息簽發(fā)一個(gè) Token,返回給客戶(hù)端
  • 客戶(hù)端存儲(chǔ) Token
  • 客戶(hù)端每次向服務(wù)器發(fā)送其它請(qǐng)求時(shí),都要攜帶 Token
  • 服務(wù)器收到請(qǐng)求,若請(qǐng)求的 API 需要驗(yàn)證身份,則先驗(yàn)證 Token,成功后再返回?cái)?shù)據(jù)

Token 的組成

構(gòu)造 Token 的方法較多,只要客戶(hù)端和服務(wù)端約定好了生成和驗(yàn)證的格式,則有很多自定義的方法。當(dāng)然,也有一些標(biāo)準(zhǔn)的寫(xiě)法,例如 JWT,讀作 /jot/,表示 JSON Web Tokens。

JWT 標(biāo)準(zhǔn)的 Token 有三個(gè)部分:

  • header
  • payload
  • signature

三個(gè)部分使用 . 分隔開(kāi),且使用 Base64 編碼,示例如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJuaW5naGFvLm5ldCIsImV4cCI6IjE0Mzg5NTU0NDUiLCJuYW1lIjoid2FuZ2hhbyIsImFkbWluIjp0cnVlfQ.SwyHTEx_RQppr97g4J5lKXtabJecpejuef8AqKYMAJc

Header

Header 主要蘊(yùn)含兩部分內(nèi)容的信息,分別是 Token 的類(lèi)型和加密使用的方法。

初始數(shù)據(jù)對(duì)象示例如下:

{
    "typ": "JWT",
    "alg": "HS256"
}

上述數(shù)據(jù)對(duì)象在經(jīng)過(guò)算法加密、Base64 編碼后,變?yōu)?Token 的第一部分:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

Payload

Payload 為 Token 的具體內(nèi)容,下面是可選的標(biāo)準(zhǔn)字段,也可以自定義添加需要的內(nèi)容。

  • iss: Issuer, 發(fā)行者
  • sub: Subject, 主題
  • aud: Audience, 觀(guān)眾
  • exp: Expiration time, 過(guò)期時(shí)間, 可為時(shí)間戳格式
  • nbf: Not before
  • iat: Issued at, 發(fā)行時(shí)間, 可為時(shí)間戳格式
  • jti: JWT ID

同樣的,該部分初始數(shù)據(jù)對(duì)象經(jīng)過(guò)算法加密、Base64 編碼后,變?yōu)?Token 的第二部分。

Signature

Signature 為 Token 的簽名部分,相當(dāng)于是前兩部分的簽名,用于防止其他人篡改 Token 中的信息。在處理時(shí),可以將生成的 Token 前兩段內(nèi)容,使用 MD5 等簽名算法進(jìn)行處理,將結(jié)果作為本部分內(nèi)容。

加密算法

從上面對(duì) Token 組成部分的介紹中,可以了解到,在規(guī)定 Token 需蘊(yùn)含的數(shù)據(jù)信息后,需要經(jīng)過(guò)一定的算法加密、Base64 編碼后成為 Token 的第一、二部分。因此,在生成 Token 時(shí),要解決使用什么加密算法。

此處的加密算法一定要是可逆的、可解密的,因?yàn)槲覀儾粌H要生成 Token,還要能從 Token 中解析出我們生成時(shí)存儲(chǔ)的數(shù)據(jù),以驗(yàn)證用戶(hù)信息和 Token 的有效期。因此,這里不能采用 MD5、SHA1 這樣的哈希算法,因?yàn)樗鼈儫o(wú)法解密,只能用于生成簽名。

在 Django 中內(nèi)置了加密模塊 django.core.signing,我們調(diào)用其中的 dumpsloads 函數(shù)實(shí)現(xiàn)加密和解密。

示例:

from django.core import signing
data = {
    "username": "Zewan"
}
value = signing.dumps(data) # encrypt
raw = signing.loads(value)  # decrypt
print(value, src)

Django 生成和驗(yàn)證 Token

上面我們已經(jīng)了解了 Token 機(jī)制的流程和采取的加密算法,接下來(lái)介紹 Django 中如何編寫(xiě)代碼以實(shí)現(xiàn) Token 機(jī)制。

我規(guī)定 Token 的 Header 部分為 {"typ": "JWP", "alg": "default"},Payload 部分含有用戶(hù)名 username 和過(guò)期時(shí)間 exp,Signature 我使用 MD5 算法生成簽名。在登錄成功后,后端返回給前端 username 和 Token,由前端存儲(chǔ)起來(lái);當(dāng)前端發(fā)送需要驗(yàn)證身份信息的請(qǐng)求時(shí),將 username 和 Token 加入請(qǐng)求頭中,后端從請(qǐng)求頭獲取這兩部分,從 Token 中解析得到用戶(hù)名和過(guò)期時(shí)間,核驗(yàn)請(qǐng)求頭中的 username 是否正確及 Token 是否有效。

處理 Token

我在 utils/token.py 文件中實(shí)現(xiàn) Token 的生成和解析數(shù)據(jù)的功能:

import time
from django.core import signing
import hashlib

HEADER = {'typ': 'JWP', 'alg': 'default'}
KEY = "Zewan"
SALT = "blog.zewan.cc"

def encrypt(obj):
    """加密:signing 加密 and Base64 編碼"""
    value = signing.dumps(obj, key=KEY, salt=SALT)
    value = signing.b64_encode(value.encode()).decode()
    return value

def decrypt(src):
    """解密:Base64 解碼 and signing 解密"""
    src = signing.b64_decode(src.encode()).decode()
    raw = signing.loads(src, key=KEY, salt=SALT)
    return raw

def create_token(username):
    """生成token信息"""
    # 1. 加密頭信息
    header = encrypt(HEADER)
    # 2. 構(gòu)造Payload(有效期14天)
    payload = {"username": username, "iat": time.time(), 
               "exp": time.time()+1209600.0}
    payload = encrypt(payload)
    # 3. MD5 生成簽名
    md5 = hashlib.md5()
    md5.update(("%s.%s" % (header, payload)).encode())
    signature = md5.hexdigest()
    token = "%s.%s.%s" % (header, payload, signature)
    return token

def get_payload(token):
    """解析 token 獲取 payload 數(shù)據(jù)"""
    payload = str(token).split('.')[1]
    payload = decrypt(payload)
    return payload

def get_username(token):
    """解析 token 獲取 username"""
    payload = get_payload(token)
    return payload['username']

def get_exp_time(token):
    """解析 token 獲取過(guò)期時(shí)間"""
    payload = get_payload(token)
    return payload['exp']

def check_token(username, token):
    """驗(yàn)證 token:檢查 username 和 token 是否一致且未過(guò)期"""
    return get_username(token) == username and get_exp_time(token) > time.time()

登錄成功批發(fā) Token

在登錄請(qǐng)求處理函數(shù)中,驗(yàn)證用戶(hù)名和密碼成功后,調(diào)用 utils/token.py 文件中的 create_token 函數(shù)生成 token,并將 username 和 token 返回前端。代碼較為簡(jiǎn)單,此處不多展示。

中間件攔截驗(yàn)證 (Middleware)

創(chuàng)建一個(gè)中間件(Middleware),在前端請(qǐng)求需要身份核驗(yàn)的后端路由時(shí),由該中間件核驗(yàn)其 username 和 token,驗(yàn)證成功后再放行,進(jìn)入業(yè)務(wù)處理的 API 中。

我的項(xiàng)目名稱(chēng)為 backend_demo,在自動(dòng)生成的 backend_demo 包中,我創(chuàng)建 middleware.py 文件,構(gòu)建中間件。該文件內(nèi)容如下:

提示:前端向請(qǐng)求頭添加 xxx 信息,一般會(huì)自動(dòng)轉(zhuǎn)變?yōu)?HTTP_XXX (全部大寫(xiě))

from utils.token import check_token
from django.http import JsonResponse

try:
    from django.utils.deprecation import MiddlewareMixin  # Django 1.10.x
except ImportError:
    MiddlewareMixin = object

# 白名單,表示請(qǐng)求里面的路由時(shí)不驗(yàn)證登錄信息
API_WHITELIST = ["/api/user/login", "/api/user/register"]

class AuthorizeMiddleware(MiddlewareMixin):
    def process_request(self, request):
        if request.path not in API_WHITELIST:
            # 從請(qǐng)求頭中獲取 username 和 token
            username = request.META.get('HTTP_USERNAME')
            token = request.META.get('HTTP_AUTHORIZATION')
            if username is None or token is None:
                return JsonResponse({'errno': 100001, 'msg': "未查詢(xún)到登錄信息"})
            else:
                # 調(diào)用 check_token 函數(shù)驗(yàn)證
                if check_token(username, token):
                    pass
                else:
                    return JsonResponse({'errno': 100002, 
                                         'msg': "登錄信息錯(cuò)誤或已過(guò)期"})

實(shí)現(xiàn)中間件后,將其添加進(jìn)項(xiàng)目中,在 settings.py 文件的 MIDDLEWARE 中添加建立的中間件:

MIDDLEWARE = [
    'backend_demo.middleware.AuthorizeMiddleware',
    # ...
]

Vue 存儲(chǔ)和攜帶 Token

登錄成功存儲(chǔ) Token

登錄成功后,前端獲取并存儲(chǔ)后端返回的 username 和 token。前端實(shí)現(xiàn)存儲(chǔ)的方式有很多,我這里使用簡(jiǎn)單的方法,將其存儲(chǔ)在 localStorage 中。

// 此處用 username 和 authorization 表示,放到項(xiàng)目中要依據(jù)情況修改該變量標(biāo)識(shí)
localStorage.setItem("username", username);
localStorage.setItem("authorization", authorization);

請(qǐng)求頭攜帶用戶(hù)名和 Token

接下來(lái)實(shí)現(xiàn)請(qǐng)求頭攜帶用戶(hù)名和 Token 信息。

在 Vue.js 實(shí)現(xiàn)的項(xiàng)目中,我一般是用 Axios 向后端發(fā)送請(qǐng)求。在 Axios 中,不需要在每一處請(qǐng)求的代碼中添加請(qǐng)求頭代碼,只需要在 main.js 中配置 Axios 的默認(rèn)請(qǐng)求器,即可使所有的請(qǐng)求中 headers 都攜帶用戶(hù)名和 token。

main.js 中核心代碼如下:

提示:這里填入 headers 中雖然是 usernameauthorization,但會(huì)被自動(dòng)轉(zhuǎn)化為 HTTP_USERNAMEHTTP_AUTHORIZATION

import axios from 'axios';

// add username and token into headers
axios.interceptors.request.use(
    config => {
        var username = localStorage.getItem('username');
        var authorization = localStorage.getItem('authorization');
        // 若 localStorage 中含有這兩個(gè)字段,則添加入請(qǐng)求頭
        if (username & authorization) {
            config.headers.authorization = authorization;
            config.headers.username = username;
        }
        return config;
    },
    error => {
        return Promise.reject(error);
    }
);

這樣,就在 Vue.js 和 Django 編寫(xiě)的前后端項(xiàng)目中,實(shí)現(xiàn)了基于 Token 的身份驗(yàn)證機(jī)制。其他前后端框架的 Token 實(shí)現(xiàn)原理與本文一致,但是代碼需要根據(jù)所用框架進(jìn)行合理修改。

到此這篇關(guān)于Vue 和 Django 實(shí)現(xiàn) Token 身份驗(yàn)證的流程的文章就介紹到這了,更多相關(guān)Vue  Django身份驗(yàn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue項(xiàng)目如何配置git忽略文件

    Vue項(xiàng)目如何配置git忽略文件

    這篇文章主要介紹了Vue項(xiàng)目如何配置git忽略文件問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • vue3+ElementPlus封裝函數(shù)式彈窗組件詳解

    vue3+ElementPlus封裝函數(shù)式彈窗組件詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用vue3和ElementPlus封裝函數(shù)式彈窗組件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2023-08-08
  • vue3.0+element表格獲取每行數(shù)據(jù)代碼示例

    vue3.0+element表格獲取每行數(shù)據(jù)代碼示例

    這篇文章主要給大家介紹了關(guān)于vue3.0+element表格獲取每行數(shù)據(jù)的相關(guān)資料,在element-ui中,你可以通過(guò)為表格的行綁定單擊事件來(lái)獲取表格中的一行數(shù)據(jù),需要的朋友可以參考下
    2023-09-09
  • Vue.use的原理和設(shè)計(jì)源碼探究

    Vue.use的原理和設(shè)計(jì)源碼探究

    這篇文章主要為大家介紹了Vue.use的原理和設(shè)計(jì)源碼探究詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • vue實(shí)現(xiàn)面包屑的方法

    vue實(shí)現(xiàn)面包屑的方法

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)面包屑的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • 查找Vue中下標(biāo)的操作(some和findindex)

    查找Vue中下標(biāo)的操作(some和findindex)

    這篇文章主要介紹了查找Vue中下標(biāo)的操作(some和findindex),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-08-08
  • laravel5.4+vue+element簡(jiǎn)單搭建的示例代碼

    laravel5.4+vue+element簡(jiǎn)單搭建的示例代碼

    本篇文章主要介紹了laravel5.4+vue+element簡(jiǎn)單搭建的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • vue中的自定義分頁(yè)插件組件的示例

    vue中的自定義分頁(yè)插件組件的示例

    這篇文章主要介紹了vue中的自定義分頁(yè)插件組件的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • vue3前端實(shí)現(xiàn)全屏顯示及元素垂直填滿(mǎn)頁(yè)面效果

    vue3前端實(shí)現(xiàn)全屏顯示及元素垂直填滿(mǎn)頁(yè)面效果

    這篇文章主要給大家介紹了關(guān)于vue3前端實(shí)現(xiàn)全屏顯示及元素垂直填滿(mǎn)頁(yè)面效果的相關(guān)資料,文中還給大家介紹了vue3實(shí)現(xiàn)某一個(gè)元素全屏之后就黑屏了的解決辦法,需要的朋友可以參考下
    2024-02-02
  • vue使用swiper插件實(shí)現(xiàn)輪播圖的示例

    vue使用swiper插件實(shí)現(xiàn)輪播圖的示例

    這篇文章主要介紹了vue使用swiper插件實(shí)現(xiàn)輪播圖的示例,幫助大家更好的理解和學(xué)習(xí)使用vue框架,感興趣的朋友可以了解下
    2021-05-05

最新評(píng)論