DjangoRESTフレームワークJWT
1.JWTの概要
JWT(Json Web Token)はオープンスタンダード(RFC 7519)であり、通信当事者間でJSONオブジェクトの形式で情報を安全に送信するための簡潔な自己完結型の方法を定義します。JWTは、HMACアルゴリズムまたはRSA公開キーキーペアを使用して署名できます。これには2つの特徴があります。
コンパクト
データ量が少なく、伝送速度が速いため、URL、POSTパラメータ、またはHTTPヘッダーで送信できます。
自己完結型
ロードにはすべてのユーザーが必要とする情報が含まれているため、データベースへの複数のクエリを回避できます
2.JWT構成
JWTは、3つの情報の文字列です。これらの3つの情報テキストは、.
互いにリンクされてJwt文字列を形成します。このような:
最初の部分はヘッダーと呼ばれ、2番目の部分はペイロード(ペイロード、飛行機で運ばれるものと同様)と呼ばれ、3番目の部分は署名です。
ヘッダ
jwtのヘッダーには、次の2つの情報が含まれています。
- 宣言タイプ、ここにjwtがあります
- 暗号化アルゴリズムは通常、HMACSHA256を直接使用すると述べられています
完全なヘッダーは次のJSONのようになります。
{
'typ': 'JWT',
'alg': 'HS256'
}
次に、ヘッダーはbase64.b64encode()で暗号化され(暗号化は対称的に復号化できます)、最初の部分を形成します。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
pythonでのBase64の暗号化と復号化
import base64
str1 = 'admin'
str2 = str1.encode()
b1 = base64.b64encode(str2) #数据越多,加密后的字符串越长
b2 = base64.b64decode(b1) #admin
各个语言中都有base64加密解密的功能,所以我们jwt为了安全,需要配合第三段加密
ペイロード
ペイロードは、有効な情報が保存される場所です。この名前は特に飛行機で運ばれる商品を指しているようで、効果的な情報は次の3つの情報を保存できます。
- 標準に登録された宣言
- 公式声明
- プライベートステートメント
標準に登録されている宣言(推奨されますが必須ではありません):
-
iss:jwt発行者
-
sub:jwtの対象となるユーザー
-
aud:jwtを受信するパーティ
-
exp:jwtの有効期限。この有効期限は、発行時間よりも長くする必要があります。
-
nbf:jwtが使用できなくなるまでの時間を定義します。
-
iat:jwt発行時間
-
JTI:ワンタイム回避のリプレイ攻撃にトークンとして主に使用されているJWTの一意のIDを、。
上記は、JWTが選択のために指定した7つの公式フィールドです。
公式声明:あらゆる情報を公式声明に追加できます。通常、ユーザー関連情報やその他のビジネスに必要な情報を追加します。ただし、この部分はクライアントで復号化できるため、機密情報を追加することはお勧めしません。
プライベートステートメント:プライベートステートメントは、プロバイダーとコンシューマーが共同で定義するステートメントです。base64は対称的に復号化されるため、機密情報を保存することは一般に推奨されません。つまり、情報のこの部分はプレーンテキスト情報として分類できます。
ペイロード、データをjson形式で定義します。
{
"sub": "1234567890",
"exp": "3422335555", #时间戳形式
"name": "John Doe",
"admin": true
}
次に、base64.b64encode()で暗号化して、JWTの2番目の部分を取得します。
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
署名
JWTの3番目の部分はビザ情報であり、このビザ情報は3つの部分で構成されています。
- ヘッダー(base64の後)
- ペイロード(base64の後)
- 秘密鍵
この部分では、.
接続によって形成された文字列を使用するためにbase64暗号化ヘッダーとbase64暗号化ペイロードsecret
が必要です。次に、ヘッダーで宣言された暗号化方式を使用してソルトの組み合わせ暗号化を実行し、jwtの3番目の部分を構成します。
// javascript
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
var signature = HMACSHA256(encodedString, 'secret'); //xxxx // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
これらの3つの部分.
を完全な文字列に接続して、最終的なjwtを形成します。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
注:シークレットはサーバー側に保存され、jwtの署名もサーバー側にあります。シークレットはjwtの発行とjwtの検証に使用されます。したがって、これはサーバーの秘密鍵であり、どのシーンでも公開しないでください。クライアントが秘密を知ったら、それはクライアントがjwtに自己署名できることを意味します。
jwt的优点:
1. 实现分布式的单点登陆非常方便
2. 数据实际保存在客户端,所以我们可以分担都武器的存储压力
3. JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
jwt的缺点:
1. 数据保存在了客户端,我们服务端只认jwt,不识别客户端。
2. jwt可以设置过期时间,但是因为数据保存在了客户端,所以对于过期时间不好调整。#secret_key轻易不要改,一改所有客户端都要重新登录
認証フローチャート:
最初に、フロントエンドはWebフォームを介してユーザー名とパスワードをバックエンドインターフェイスに送信します。このプロセスは通常、HTTPPOSTリクエストです。推奨される方法は、SSL暗号化送信(httpsプロトコル)を使用して、機密情報が盗聴されるのを防ぐことです。
バックエンドはユーザー名とパスワードを正常にチェックした後、ユーザーのIDとその他の情報をJWTペイロード(ロード)として使用します。JWTペイロードはそれぞれBase64でエンコードされ、ヘッダーとスプライスされてJWTを形成します。結果のJWTは、lll.zzz.xxxに似た文字列です。
バックエンドは、フロントエンドへのログインが成功した結果としてJWT文字列を返します。フロントエンドは返された結果をlocalStorageまたはsessionStorageに保存でき、フロントエンドはログアウト時に保存されたJWTを削除できます。
フロントエンドは、要求するたびにJWTをHTTPヘッダーのAuthorizationビットに配置します。(XSSおよびXSRFの問題を解決します)
5.后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。
3.使用
1.インストール:
pip install djangorestframework-jwt -i https://mirrors.aliyun.com/pypi/simple/
2.構成設定ファイルで
https://github.com/jpadilla/django-rest-framework-jwt
を構成します。
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
import datetime
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
- JWT_EXPIRATION_DELTAは、トークンの有効期間を示します
jwtを手動で生成する
Django RESTフレームワークJWT拡張機能のドキュメントには、手動でJWTを発行する方法が記載されています。
from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
サブアプリルーティングurls.py
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path(r'login/', obtain_jwt_token),
]
メインルートで、現在のサブアプリケーションのルートファイルをインポートします
urlpatterns = [
...
path('user/', include("users.urls")),
# include 的值必须是 模块名.urls 格式,字符串中间只能出现一个圆点
]
フロントエンドセーブjwt
JWTはCookieまたはブラウザのローカルストレージに保存できます。ブラウザのローカルストレージに保存します。
ブラウザのローカルストレージには、ウィンドウオブジェクトに属するsessionStorageとlocalStorageの2つのタイプがあります。
- ブラウザを閉じると、sessionStorageが無効になります
- localStorageは長期間有効です
指示
sessionStorage.变量名 = 变量值 // 保存数据
sessionStorage.setItem("变量名","变量值") // 保存数据
sessionStorage.变量名 // 读取数据
sessionStorage.getItem("变量名") // 读取数据
sessionStorage.removeItem("变量名") // 清除单个数据
sessionStorage.clear() // 清除所有sessionStorage保存的数据
localStorage.变量名 = 变量值 // 保存数据
localStorage.setItem("变量名","变量值") // 保存数据
localStorage.变量名 // 读取数据
localStorage.getItem("变量名") // 读取数据
localStorage.removeItem("变量名") // 清除单个数据
localStorage.clear() // 清除所有sessionStorage保存的数据