Json web token (JWT)
, 是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON
的開放標準((RFC 7519).該token
被設計爲緊湊且安全的,特別適用於分佈式站點的單點登陸(SSO
)場景。JWT
的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token
也可直接被用於認證,也可被加密。html
session認證的流程通常以下:python
用戶向服務器發送用戶名和密碼。web
服務器驗證經過後,在當前對話(session)裏面保存相關數據,好比用戶角色、登陸時間等等。算法
服務器向用戶返回一個 session_id,寫入用戶的 Cookie。django
用戶隨後的每一次請求,都會經過 Cookie,將 session_id 傳回服務器。瀏覽器
服務器收到 session_id,找到前期保存的數據,由此得知用戶的身份。安全
session保存在服務器,當註冊用戶不少,會增長服務器的開銷。bash
用戶認證以後,服務端作認證記錄,若是認證的記錄被保存在內存中的話,這意味着用戶下次請求還必需要請求在這臺服務器上,這樣才能拿到受權的資源,這樣在分佈式的應用上,限制了負載均衡的能力。這也意味着限制了應用的擴展能力。服務器
session是基於cookie來進行用戶識別的, cookie若是被截獲,用戶就會很容易受到跨站請求僞造(CSRF
)的攻擊。cookie
JWT
是基於token
的鑑權機制相似於http
協議也是無狀態的,它不須要在服務端去保留用戶的認證信息或者會話信息。這就意味着基於token
認證機制的應用不須要去考慮用戶在哪一臺服務器登陸了,這就爲應用的擴展提供了便利。
用戶使用用戶名密碼來請求服務器
服務器進行驗證用戶的信息
服務器經過驗證發送給用戶一個token
客戶端存儲token,並在每次請求時附送上這個token值
服務端驗證token值,並返回數據
這個token必需要在每次請求時傳遞給服務端,它應該保存在請求頭
裏, 另外,服務端要支持CORS(跨來源資源共享)
策略,通常咱們在服務端這麼作就能夠了Access-Control-Allow-Origin: *
。
第一部分咱們稱它爲頭部(header
),第二部分咱們稱其爲載荷(payload
),第三部分是簽證(signature
).
官方連接jwt.io/
jwt的頭部承載兩部分信息:
聲明類型,這裏是jwt
聲明加密的算法 一般直接使用 SHA256
# 頭部相似以下信息:{ "alg": "HS256", "typ": "JWT"}複製代碼
將頭部進行base64
加密(該加密是能夠對稱解密的),構成了第一部分.獲得的加密信息是以下的一串字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9複製代碼
載荷就是存放有效信息的地方。這些有效信息包含三個部分:
標準中註冊的聲明
公共的聲明
私有的聲明
{ "name": "John", "admin": true, 「email」:"xxx@gmail.com"}複製代碼
該部分也是base64
加密的,加密後獲得下面字符串:
ewogICJuYW1lIjogIkpvaG4iLAogICJhZG1pbiI6IHRydWXvvIwKICDigJxlbWFpbOKAnToieHh4QGdtYWlsLmNvbSIKfQ複製代碼
JWT
的第三部分是一個簽證信息,這個簽證信息由三部分組成:
header
(base64
加密)
payload
(base64
加密)
secret
密鑰
這個部分須要base64
加密後的header
和base64
加密後的payload
使用.
鏈接組成的字符串,而後經過header
中聲明的加密方式進行SHA256
組合加密(不可逆加密),而後就構成了jwt
的第三部分。將這三部分用.
鏈接成一個完整的字符串,構成了最終的jwt
。
注意:secret
是保存在服務器端的,jwt
的簽發生成也是在服務器端的,secret
就是用來進行jwt
的簽發和jwt
的驗證,因此,它就是你服務端的私鑰,在任何場景都不該該流露出去。一旦客戶端得知這個secret
, 那就意味着客戶端是能夠自我簽發jwt
了。若是以爲密鑰泄露了,請及時修改。
下面介紹的是在djangorestframework
基礎上的jwt
集成方案。首先確保djangorestframework
在設置文件中應用中註冊。
安裝
pip install djangorestframework-jwt複製代碼
配置
INSTALLED_APPS = [
...
'djangorestframework',
...
]
# 認證
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
),
}
JWT_AUTH = {
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), # JWT_EXPIRATION_DELTA 指明token的有效期
}複製代碼
路由
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
# JWT 完成登陸
url(r'^authorizations/$', obtain_jwt_token),
]複製代碼
利用djangorestframework-jwt生成的token
值保存在瀏覽器的Storage
中。