JWTの決意
JWT:JSONウェブトークンは、一般的にサーバーからリソースを取得するために、アイデンティティで分娩室およびサービスプロバイダー認証されたユーザID情報を提供するために使用されている、あなたはまた、いくつかの追加のビジネスロジックその他の必要な情報のステートメントを追加することができますまた、直接認証のために使用することができるトークンが暗号化されてもよいです。
伝統的なセッション認証
HTTPは、ユーザーが次回の要求、アプリケーションへのユーザ認証のためのユーザー名とパスワードを提供する場合、ユーザーは再びユーザー認証のための仕事でなければならないことステートレスなプロトコル、短い接続許可書、およびこの手段であり、 httpプロトコルに従って、我々はリクエストが送信されたユーザーを知ることができないので、その要求は、ユーザによって発行されているアプリケーションを識別することができるようにするために、我々はできるサーバーのコピー保存ログインユーザー、すなわちセッションを。
ログインセッションはそうすることを、クッキーに保存され、ブラウザに応じて、渡されたキャリー・セッションに次の要求あなたがからのユーザー要求を識別することができ、これは伝統的なセッションベースの認証であるので、。
セッションベースの認証の問題を暴露
- 各ユーザ認証の後、あなたはそれがメモリに格納されている場合、セッションを保存する必要があり、認証されたユーザの増加とともに、サーバーの支出は大幅に増加します。
- スケーラビリティ:認証レコードはメモリに保存されている場合、この手段は次回というユーザーの要求も、そのための分散アプリケーション、対応する制限を許可を取得するように、このサーバ上のリソースを要求するには持っていますバランサをロードする機能。アプリケーションのスケーラビリティを制限これも手段。
- CSRFは:傍受クッキー場合、ユーザーは、クロスサイトリクエストフォージェリ攻撃に対して脆弱である可能性があります。
トークンベースの認証
これは、ユーザーの認証情報やセッション情報を保持するサーバーを必要としません。トークン認証メカニズムに基づいたアプリケーションは、ユーザが拡張性を持っているサーバでは、セキュリティ、ログインして検討する必要がないことをこれが意味。
プロセス:
- サーバ要求にユーザ名とパスワードのユーザー
- ユーザーの情報を確認するために、サーバー
- サーバーは、トークンを検証することにより、ユーザに送信します
- クライアントストレージトークン、このトークン値及び各要求に運び
- サーバー認証トークン、およびデータを返します。
トークンは、サーバーへの要求ごとに渡される必要があり、それがサポートするサーバー、加えて、事前のリクエストに保管しなければならないCORS(跨来源资源共享)
戦略を、我々は通常、サーバー側でそれを行いますAccess-Control-Allow-Origin: *
。
JWT:
JWT形式
JWTはJWT文字列を構成すると共にテキストリンクを有する3つの情報、これら3つの情報から構成されています。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
構造:
header: {'typ':'JWT',"alg":'HS256'}
payload: {"user_id":1, 'username':'xx', 'exp':'超时时间'}
signature: 前两部分加密后拼接,在加密
ヘッドヘッダ:{ '標準': 'JWT'、 "ALG": 'HS256'}
- 宣言された型、ジェット
- 声明アルゴリズム、ライン256の数
ヘッドは、次いで、第1の部分を構成する、base64ulrために暗号化されています
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
負荷ペイロード:{ "USER_ID" :. 1、 'ユーザ名': 'XX'、 'EXP': 'タイムアウト'}いくつかの有効な情報が格納され、機密情報は推奨されません。
標準的な登録届出書(必須ではありません):
ISS:JWTの発行者
サブ:ユーザーのためのJWT
AUD:受信側JWT
EXP:JWT有効期限、有効期限は、時間の問題よりも大きくなければなりません。
NBF:JWTの前に定義されてどのような時間は利用できません。
IAT:時間の問題JWT
JTI:JWT独自のアイデンティティは、主にリプレイ攻撃を避けるために、ワンタイムトークンとして使用されています
公式声明
ユーザーに関する一般的な情報は、必要な情報やその他のビジネスニーズを追加します。
この部分は、例えば、第2の部分を構成する、base64urlを暗号化されます。
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
署名署名:
列のこの部分は、で暗号化された上記の二つの部分を与える
.
、例えば、暗号化base64url、第三の部分次いで、ステッチ、次いでhs256を暗号化するために、塩:TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
次いで、上部に
.
接続、最終的なトークンの組成物。
ユーザ認証が成功した場合は、ブラウザを与えるトークン文字列を返すサーバは、次回リクエストを保存しません、それはトークン運ぶでしょう
- 高度な検証タイムアウト(ExpriredSignature)
- 合法性検証トークン(比較一部最初の二つによって暗号化されました)
利点:
- トークンは、フロントエンドで、バックエンドは、検証のための唯一の責任である保存されました。
- タイムアウト、後端が時間に基づくことができるかどうかタイムアウトチェックを統合します。
- 内部暗号化hs256のためには、それは限り修正認証が失敗したとして、トークンを変更することはできません。
- サーバ内の店舗セッション情報への必要はありませんので、アプリケーションを拡張することは容易ではありません。
短所:
- 発行されたトークンの後、手動で期限切れにすることはできません。
DRFで使用されているJWT
インストール
pip3 install djangorestframework-jwt
setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'api.apps.ApiConfig',
'rest_framework',
'rest_framework_jwt' # 注册
]
# JWT过期时间设置
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(minutes=10), # 10分钟过期
}
ユーザーログイン
import uuid
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning
from rest_framework import status
from rest_framework_jwt.settings import api_settings
from api import models
class LoginView(APIView):
"""
登录接口
"""
def post(self,request,*args,**kwargs):
# 基于jwt的认证
# 1.去数据库获取用户信息
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
user = models.UserInfo.objects.filter(**request.data).first()
if not user:
return Response({'code':1000,'error':'用户名或密码错误'})
payload = jwt_payload_handler(user) # 产生第二段的字典类型{'user_id':1, 'username':xxx, 'exp':当前时间+过期时间段}
token = jwt_encode_handler(payload) # 加密生成jwt的token(加密、拼接全做)
return Response({'code':1001,'data':token})
ユーザー認証
from rest_framework.views import APIView
from rest_framework.response import Response
# from rest_framework.throttling import AnonRateThrottle,BaseThrottle
import jwt
from rest_framework import exceptions
from rest_framework_jwt.settings import api_settings
class ArticleView(APIView):
# throttle_classes = [AnonRateThrottle,]
def get(self,request,*args,**kwargs):
# 获取用户提交的token,进行一步一步校验
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
jwt_value = request.query_params.get('token')
try:
payload = jwt_decode_handler(jwt_value) # 校验
except jwt.ExpiredSignature:
msg = '签名已过期'
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = '认证失败'
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenpythonticationFailed()
print(payload) # 检验后的第二段数据
return Response('文章列表')