天天看點

JWT身份認證

一:背景項目的準備工作:

<一>: 項目的安裝環境配置

1:将前端工程導入ubuntu中,然後進入目錄:

cd meiduo_mall_admin
           

2:安裝依賴包npm

npm install
           

3:将目錄拖入原來的商城目錄中,再進入meiduo_mall_admin目錄中。

4:使用指令運作背景項目:

npm run dev
           

或者

cd dist/
python3 -m http.server 8081
           

<二>: django項目的配置:

1:建立meiduo_admin應用:

INSTALL_APPS = [
  # ...
  'apps.meiduo_admin'
]
           

總路由:

urlpatterns = [
  # ....
  re_path(r'^meiduo_admin/', include('apps.meiduo_admin.urls')),
]
           

2:配置檔案中修改跨域白名單:

# 添加跨域白名單,指定允許跨域請求到8000的源
CORS_ORIGIN_WHITELIST = [
    # 美多商城跨域請求源
    'http://www.meiduo.site:8080',
    'http://127.0.0.1:8080',
    # 管理站點跨域請求的源
    'http://www.meiduo.site:8081'
]
           

二:JWT原理分析:

<一>: 狀态保持的三種方式的對比:

1:cookie機制:

JWT身份認證

2:session機制:

JWT身份認證

3:JWT技術:

JWT身份認證

<二>: 單點登入:

JWT身份認證

<三>tocken令牌的格式:

JWT身份認證

三:tocken的簽發:

<一>: 簽發流程:

1:頭部資訊的簽發:

思路:頭部包含:簽發類型和加密方式。 字典—>json —>經過b64編碼成字元串

header = {
        'typ': "JWT",
        'alg': "HS256",
    }

    # 1:将頭部資訊變成json
    header = json.dumps(header)
    # 2:将json加密成位元組形式
    header = header.encode()# b'{"alg": "HS256", "typ": "JWT"}'
    # 3: 将位元組進行b64編碼
    header = base64.b64encode(header)# b'eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9'
    # 4: 将編碼後的再轉化成字元串
    header = header.decode() # eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9
           

2:載荷資訊簽發:

payload = {
    'username': 'renshanwen',
    'user_id': 1,
    'age': 18
}
payload = json.dumps(payload)
payload = base64.b64encode(payload.encode()).decode()
print('payload: ', payload)
           

載荷中除了記錄自定義使用者資料以外,還有jwt标準中約定的其他資訊,如下(建議但不強制使用)

iss: jwt簽發者
sub: jwt所面向的使用者
aud: 接收jwt的一方
exp: jwt的過期時間,這個過期時間必須要大于簽發時間
nbf: 定義在什麼時間之前,該jwt都是不可用的.
iat: jwt的簽發時間
jti: jwt的唯一身份辨別,主要用來作為一次性token,進而回避重播攻擊。
           

3:簽名資訊生成:

思路:加密密鑰采用django的預設配置檔案的加密密鑰。将頭部資訊和荷載資訊使用雜湊演算法進行加密,生成簽名。這個簽名就具備了唯一的辨別。

#: 簽名資訊的生成
    # 1:django的秘鑰
    SECRET_KEY = '86j_0^*mri+88x)w*wdoiv=%7sd+c4g66f#zm7t1uen^mb!h8y'

    # 2:頭部資訊+荷載資訊
    message = header + '.' + payload

    # 3:秘鑰,資訊,生成簽名算法來建立一個加密對象
    h_obj = hmac.new(key=SECRET_KEY.encode(), msg=message.encode(), digestmod=hashlib.sha256)

    # 4:使用對象的方法生成簽名資訊
    signature = h_obj.hexdigest()

    print("簽名:", signature)
    # 簽名: f419ea236196a731f1394e200703e16a8040cdbe72a53c8f2cfcad011cfa0b86
           
# 構造JWTtocken
    JWT_TOKEN = header + '.' + payload + '.' + signature
           

四:tocken的校驗:

# 假設前端傳過來的值是相同的

    token_from_browser = JWT_TOKEN
    # 擷取 頭部資訊,荷載資訊,和簽名
    old_header = token_from_browser.split('.')[0]
    old_payload = token_from_browser.split('.')[1]
    old_signature = token_from_browser.split('.')[2]

    # 把資訊按照相同的密鑰和算法,重新生成新的簽名
    message = old_header + '.' + old_payload
    new_h_obj = hmac.new(key=SECRET_KEY.encode(), msg=message.encode(), digestmod=hashlib.sha256)
    new_signature = new_h_obj.hexdigest()

    if old_signature == new_signature:
        # 有效
        print('驗證成功')
        # 提取使用者資料
        user_json = base64.b64decode(old_payload.encode()).decode()
        user_dict = json.loads(user_json)
        print("解析出來的使用者身份資訊:", user_dict)
    else:
        # 無效
        print("驗證失敗")