天天看點

JWT原理與使用

JWT

  • 什麼是JWT??
    • JWT是指

      json web token

      一般用于使用者認證,常用有(api,小程式,前後端分離)的項目
  • jwt 原理請求圖
    JWT原理與使用
  • 基于傳統的token認證
    • 使用者登入,服務端傳回token給使用者,并儲存token。
    • 當使用者再次通路時,攜帶token發起請求,服務端,查詢資料庫,對比token,token正确認證通過
  • 基于JWT token認證
    • 使用者登入,服務端傳回token(服務端不儲存)給使用者。
    • 當使用者再次通路時,攜帶token發起請求,服務端拿到token後,再做token檢驗。
    • 優勢:相比于傳統,它token不用儲存,減小資料庫的查詢,減小伺服器的壓力。

JWT 實作過程

使用者登入成功,使用

jwt

建立一個

token

并傳回給使用者
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

注意:jwt 生成的token是由三段字元串組成的,并由

.

連接配接而成的

  • 第一段字元串,

    HEADER

    ,内部包含算法和token類型。

{

“alg”: “HS256”,

“typ”: “JWT”

}

通過json轉化成字元串,然後通過

base64url

加密而成

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
  • 第二段字元串,

    PAYLOAD

    ,内部是自定義值

{

“phone”: “1234567890”,

“name”: “name”,

“exp”: “12” # 逾時時間

}

通過json轉化成字元串,然後通過

base64url

加密而成

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ
  • 第三段字元串:
    • 第一步:把第一、第二段密文拼接起來
      eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

      eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

    • 第二步:把第一步拼接起來的密文進行

      HS256 + 加鹽

      加密
    • 第三步:對

      HS256

      加密後的密文,再進行

      base64url

      加密
當使用者再次通路時,需要攜帶token,後端需要進行token檢驗
  • 擷取token
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.

    eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ

    .SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • 第一步:切割token
  • 第二步:對第二段密文進行

    base64url

    解密,并擷取

    payload

    資訊檢測token是否已經失效

    {

    “phone”: “1234567890”,

    “name”: “name”,

    “exp”: “12” # 逾時時間

    }

  • 第三步:把第一、第二段密文拼接起來,進行

    HS256 + 加鹽

    加密
    SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
    密文 =

    base64url

    解密(使用者帶來的token中的第三段:SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c)

    如果相等,則說明token未被修改過,認證通過。

Python 實作過程
  • pip install pyjwt

import jwt
import datetime
from jwt import exceptions

# 鹽值
SALT = safa
def create_token():
    # 構造header
    headers = {
        'typ': 'jwt',
        'alg': 'HS256'
    }
    # 構造payload
    payload = {
        'user_id': 1, # 自定義使用者ID
        'username': 'name', # 自定義使用者名
        'exp': datetime.datetime.utcnow() + datetime.timedelta(minutes=5) # 逾時時間
    }
    result = jwt.encode(payload=payload, key=SALT, algorithm="HS256", headers=headers).decode('utf-8')
    return result
    
def get_payload(token):
    """
    根據token擷取payload
    :param token:
    :return:
    """
    try:
        verified_payload = jwt.decode(token, SALT, True)
        return verified_payload
    except exceptions.ExpiredSignatureError:
        print('token已失效')
    except jwt.DecodeError:
        print('token認證失敗')
    except jwt.InvalidTokenError:
        print('非法的token')
if __name__ == '__main__':
	# jwt 生成token
    token = create_token()
    
    # jwt 檢驗token
    payload = get_payload(token)