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)