一、什麼是JSON Web令牌?
JSON Web令牌(JSON Web Token,JWT)是一種基於JSON的安全傳輸信息的開放標準,主要用於在網絡應用中傳遞聲明,以便於在服務端進行校驗,保證數據的安全性和完整性。
一個JWT實際上就是一個字符串,它由三部分組成,分別是頭部(header)、負載(payload)和簽名(signature)。其中,頭部和負載都是JSON格式的數據,在JWT中用Base64Url編碼表示。簽名則是用於驗證消息的完整性的一串字符,由頭部、負載、密鑰和加密算法共同生成。以下是一個JWT的示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
上面的JWT由三部分組成,分別是以.分隔的頭部、負載和簽名。下面我們將對其進行逐一解析。
1. JWT的頭部
JWT的頭部主要用於描述關於該JWT的最基本信息,如所使用的加密算法等。頭部的格式如下:
{ "alg": "HS256", "typ": "JWT" }
其中,alg表示簽名算法,常用的有HS256、HS384、HS512、RS256、RS384、RS512、ES256、ES384、ES512等。
2. JWT的負載
JWT的負載主要用於存儲需要傳遞的數據,如用戶ID、過期時間、權限等信息。負載的格式是一個JSON對象,可以自由地定義自己需要的字段。
{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }
上面示例中,sub表示用戶ID,name表示用戶名,iat表示JWT的簽發時間。
3. JWT的簽名
JWT的簽名是用於驗證JWT的完整性,防止數據被篡改。簽名的生成需要使用一個密鑰,對頭部和負載進行加密,然後再與密鑰一起通過指定的簽名算法生成簽名。簽名的生成示例代碼如下:
import base64 import hmac import hashlib header = base64.urlsafe_b64encode(b'{"alg": "HS256", "typ": "JWT"}').rstrip(b'=') payload = base64.urlsafe_b64encode(b'{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}').rstrip(b'=') secret = 'your-256-bit-secret' message = header + b'.' + payload signature = hmac.new(key=secret.encode('utf-8'), msg=message, digestmod=hashlib.sha256).digest() jwt = message + b'.' + base64.urlsafe_b64encode(signature).rstrip(b'=') print(jwt.decode('utf-8'))
以上代碼主要實現了對於header和payload的base64編碼以及簽名的生成。其中,b’=’是多餘的填充字符,使用rstrip函數進行去除,生成最終的jwt。
二、Python中如何使用JWT實現身份驗證?
在使用JWT進行身份驗證時,常見的使用方式是把JWT編碼後存放在請求的頭部,如下所示:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
需要注意的是,Bearer是一種認證機制,用於告知服務器該請求是帶有訪問令牌的請求。
在Python中,我們可以藉助PyJWT庫來實現JWT的生成和驗證功能。以下是一個使用PyJWT實現JWT身份驗證的示例:
import jwt import datetime from functools import wraps from flask import Flask, jsonify, request app = Flask(__name__) app.config['SECRET_KEY'] = 'your-secret-key' def token_required(func): @wraps(func) def decorated(*args, **kwargs): token = request.headers.get('Authorization').split(' ')[1] if not token: return jsonify({'message' : 'Token is missing!'}), 401 try: data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"]) except: return jsonify({'message' : 'Token is invalid!'}), 401 return func(*args, **kwargs) return decorated @app.route('/login') def login(): auth = request.authorization if auth and auth.password == 'password': token = jwt.encode({'user' : auth.username, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30)}, app.config['SECRET_KEY'], algorithm='HS256') return jsonify({'token' : token}) return make_response('Could not verify!', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'}) @app.route('/protected') @token_required def protected(): return jsonify({'message' : 'Logged in successfully!'}) if __name__ == '__main__': app.run()
上面的代碼中,我們使用了一個token_required裝飾器,用於驗證請求是否帶有正確的JWT令牌。在登錄時,首先需要進行身份驗證,接着生成JWT令牌並返回。在需要進行身份驗證的接口中,使用token_required裝飾器進行驗證,對未授權的請求進行攔截。
三、使用JWT帶來的好處
1. 無需存儲用戶狀態
使用JWT進行用戶身份驗證時,無需在服務器端存儲用戶的登錄狀態,從而減輕服務器的負擔,提高服務器的性能。
2. 單點登錄(SSO)功能
使用JWT進行身份驗證時,可以將JWT令牌存儲在客戶端的Cookie或LocalStorage中,實現跨域單點登錄(SSO)的功能。
3. 良好的可擴展性
使用JWT進行身份驗證時,負載中可以存儲任意的字段信息,可以方便地擴展業務功能,不需要額外修改現有的代碼。
四、小結
通過以上介紹,我們了解了JSON Web令牌(JWT)是一種基於JSON的安全傳輸信息的開放標準,可以在網絡應用中實現用戶身份驗證的功能。在Python中,我們可以通過PyJWT庫來實現JWT的生成和驗證。使用JWT帶來的好處包括無需存儲用戶狀態、單點登錄(SSO)功能和良好的可擴展性。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/155507.html