既然要來學習jwt(json web token),那麼咱們確定是先要了解jwt的優點以及應用場景--跨域認證。python
$ pip install djangorestframework-jwt
一、用戶向服務器發送用戶名和密碼。web
二、服務器驗證經過後,在當前對話(session)裏面保存相關數據,好比用戶角色、登陸時間等等。django
在django session表中,session_key,session_data,expire_date.其中session_data保存的是base64編碼後的用戶對象。json
import base64 r = base64.b64decode("NDQ3OGI4MDA3YTI3MzM2NTQ5ZjhhZGZhNzM0ZjM2OWNlOTFmYWQ0ODp7Il9hdXRoX3VzZXJfaWQiOiIxIiwiX2F1dGhfdXNlcl9iYWNrZW5kIjoiZGphbmdvLmNvbnRyaWIuYXV0aC5iYWNrZW5kcy5Nb2RlbEJhY2tlbmQiLCJfYXV0aF91c2VyX2hhc2giOiIyOTBkMjY0YzY3MmMyYmNjZWFiZDRkZWJlZGJjMmQyM2QzNzI5YjBkIn0=") print(r) >>> b'4478b8007a27336549f8adfa734f369ce91fad48:{"_auth_user_id":"1","_auth_user_backend":"django.contrib.auth.backends.ModelBackend","_auth_user_hash":"290d264c672c2bcceabd4debedbc2d23d3729b0d"}'
三、服務器向用戶返回一個 session_id,寫入用戶的 Cookie。後端
四、用戶隨後的每一次請求,都會經過 Cookie,將 session_id 傳回服務器。api
五、服務器收到 session_id,找到前期保存的數據,由此得知用戶的身份。跨域
這種模式的問題在於,擴展性很差。單機固然沒有問題,若是是服務器集羣,或者是跨域的服務導向架構,就要求 session 數據共享,每臺服務器都可以讀取 session。服務器
由header,payload,signature三個部分組成cookie
舉個栗子session
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InJvb3QiLCJleHAiOjE1NTI5NzE5ODIsImVtYWlsIjoiMTc4NTg4MDQyNjRAMTYzLmNvbSJ9.KuZq40SkiEz9La1wzXy20irjbckNJ0SNWq2EvXBwf0A
每部分由.分隔,其中header和payload可由base64直接decode可得
header
{"typ":"JWT","alg":"HS256"}
payload
用戶信息,django中取決於UserProfile,UserProfileSerializer
signature
對前兩部分的簽名,防止數據被篡改。指定一個密鑰,使用header中的加密方式
token = base64.b64encode(bytes_header)+"."+base64.b64encode(bytes_payload)+"."+secret
settings.py
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), } JWT_AUTH = { # 指明token的有效期 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), }
該認證方案使用 HTTP Basic Authentication,並根據用戶的用戶名和密碼進行簽名。Basic Authentication 一般只適用於測試。
此認證方案使用 Django 的默認 session 後端進行認證。Session 身份驗證適用於與您的網站在同一會話環境中運行的 AJAX 客戶端。
urls.py
from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ # ... url(r'^api-token-auth/', obtain_jwt_token), ]
集成完後的測試代碼
import json import requests # 驗證jwt url = "http://127.0.0.1:8000/api-token-auth/?format=json" data = { "username": "root", "password": "Admin123." } # data = json.dumps(data) res = requests.post(url,data=data) token = res.text print("token:",token) token = json.loads(token).get("token") user_url = "http://127.0.0.1:8000/users/?format=json" headers = { "Authorization":"JWT "+ token } res = requests.get(user_url,headers=headers) print(res.text)
本身實現jwt也很是簡單
1) base64加HS256 手寫token
2) middleware 驗證token
上述1和2的傳遞是經過request參數,驗證成功後只須要咱們賦予request.user 一個user對象便可。