python3 jwt(json web token)_base64.urlsafe_b64encode()_urlsafe_b64decode()_hmac.new().py

"""
模塊:python3 jwt(json web token)_base64.urlsafe_b64encode()_urlsafe_b64decode()_hmac.new().py
功能:python3 實現 jwt 用戶驗證。
參考:https://blog.csdn.net/weixin_42193179/article/details/104475173
https://blog.csdn.net/weixin_42193179/article/details/104522302
知識點:
1.加密算法
hmac.new(key, msg=None, digestmod=None)
    創建一個新的散列對象(hashing object)並返回它。

    key: 哈希的起始鍵。
    msg: 如果可用,將立即散列到(be hashed into)對象的起始狀態。
    digestmod: 摘要(加密)模式,如SHA1、SHA224、SHA256、SHA384、SHA512、MD5等。

    現在,您可以使用它的 update() 方法將任意字符串輸入到對象中,
    並且可以通過調用它的 digest() 方法在任何時候請求哈希值。

2.base64.urlsafe_b64encode(s)
    使用url和文件系統安全的base64字母表編碼字節。

    參數s是一個用來編碼的、類似字節的對象。
    結果作爲字節對象返回。
    字母表使用'-'而不是 '+' , '_' 而不是'/'。

3.base64.urlsafe_b64decode(s)
    使用url和文件系統安全的base64字母表解碼字節。

    參數s是一個類似字節的對象或要解碼的ascii字符串。
    結果作爲字節對象返回。
    如果輸入的字節串被錯誤填充,則會引發binascii.Error。
    不在url-safe base-64字母表中的字符,而且不是加 '+' 或斜槓 '/',在填充檢查之前將被丟棄。

    字母表使用 '-' 而不是 '+' , '_' 而不是 '/'。
"""
import json
import time
import base64
import hmac

# 一、構造(JWT[json web token])
# 1.頭部。
# alg,簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);
# typ,令牌(token)的類型(type),JWT令牌統一寫爲JWT。
# 用途:將 header 對象使用 Base64URL 方法編碼成字符串,組成 JWT 結構的第一部分。
header = {"alg": "HS256", "typ": "JWT"}
headerStr = json.dumps(header)
# print(headerStr)
# {"alg": "HS256", "typ": "JWT"}
headerB64UrlEncoded = base64.urlsafe_b64encode(headerStr.encode()).decode()
print("headerB64UrlEncoded:", headerB64UrlEncoded)
# headerB64UrlEncoded: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9

# 2.負載
# 用來存放實際需要傳遞的數據(非私密)。
# iat, Issued At 簽發時間; nbf,Not Before,生效時間; exp,expiration time,過期時間。
timeStart = time.time()
payload = {"iat": timeStart, "nbf": timeStart, "exp": timeStart + 10 * 60}
payloadStr = json.dumps(payload)
payloadB64UrlEncoded = base64.urlsafe_b64encode(payloadStr.encode()).decode()
print("payloadB64UrlEncoded:", payloadB64UrlEncoded)
# payloadB64UrlEncoded: eyJpYXQiOiAxNTgyNzgxMTczLjQ3OTYwNjYsICJuYmYiOiAxNTgyNzgxMTczLjQ3OTYwNjYsICJleHAiOiAxNTgyNzgxNzczLjQ3OTYwNjZ9

# 3.簽名
# 密鑰。
secretKey = "gao2gao"
msg = headerB64UrlEncoded + "." + payloadB64UrlEncoded
signature = hmac.new(secretKey.encode(), msg.encode(), 'SHA256').hexdigest()
print("signature:", signature)
# signature: e709794583cc31eaaea84281972af97e6c589b88130acd0a692a8ac0b3e169e9

# 4.構造 JWT
jwt = msg + "." + signature
print("jwt:", jwt)
# jwt: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJpYXQiOiAxNTgyNzgxNjcyLjAzOTg3NzIsICJuYmYiOiAxNTgyNzgxNjcyLjAzOTg3NzIsICJleHAiOiAxNTgyNzgyMjcyLjAzOTg3NzJ9.771ebe03d303803d66b298753ad72d5a8be571fa732ecc6d993063893d711947


# 二、驗證 JWT
# 1.拆分header, payload, signature。
headerB64UrlEncoded, payloadB64UrlEncoded, signature = jwt.split(".")
print(headerB64UrlEncoded, payloadB64UrlEncoded, signature)
# eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9 eyJpYXQiOiAxNTgyNzgyMTAxLjExOTk4MTgsICJuYmYiOiAxNTgyNzgyMTAxLjExOTk4MTgsICJleHAiOiAxNTgyNzgyNzAxLjExOTk4MTh9 97eed8ea6656572be18de23a6bf59be013bece092ad1efcc4ff70de47547aa5a
header = json.loads(base64.urlsafe_b64decode(headerB64UrlEncoded.encode()).decode())
print("header:", header)
# header: {'alg': 'HS256', 'typ': 'JWT'}
print(type(header))
# <class 'dict'>

# 2.獲取簽名的加密算法。
alg = header['alg']
print("alg:", alg)
if alg == 'HS256':
    alg = 'SHA256'
print("alg:", alg)
# alg: SHA256

# 3.模擬用戶信息篡改。
payload = json.loads(base64.urlsafe_b64decode(payloadB64UrlEncoded.encode()).decode())
print("payload:", payload)
# payload: {'iat': 1582783148.1871371, 'nbf': 1582783148.1871371, 'exp': 1582783748.1871371}
# 篡改
payload['iss'] = 'gao'
print("payload:", payload)
# payload: {'iat': 1582783214.8349812, 'nbf': 1582783214.8349812, 'exp': 1582783814.8349812, 'iss': 'gao'}
# 重新 base64編碼。
payloadStr = json.dumps(payload)
payloadB64UrlEncoded = base64.urlsafe_b64encode(payloadStr.encode()).decode()


# 4.重新簽名(個人理解:不可破解的加密)
msg = headerB64UrlEncoded + "." + payloadB64UrlEncoded
signature2 = hmac.new(secretKey.encode(), msg.encode(), alg).hexdigest()
print("signature2:", signature2)
# signature2: e8ff3b911f27428c96feb9fca0af61fc3ff4d233bd69e955ec880eb06619003a
if signature == signature2:
    print("驗證通過!")
else:
    print("用戶信息已被篡改!")
# 驗證通過!
# 用戶信息已被篡改!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章