JWT認證登錄
最近在做一個審覈系統,後臺登錄用到JWT登錄認證,在此主要做個總結
JWT是什麼
Json web token (JWT), 根據官網的定義,是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準.該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登錄場景。JWT的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。
爲什麼使用JWT
此處主要和傳統的session作對比,傳統的session在服務器端需要保存一些登錄信息,通常是在內存中,在後端服務器是集羣等分佈式的情況下,其他主機沒有保存這些信息,所以都需要通過一個固定的主機進行驗證,如果用戶量大,在認證這個點上容易形成瓶頸,是應用不易拓展。
JWT原理
JWT由三個部分組成,用點號分割,看起來像是這樣,JWT token本身沒有空格換行等,下面是爲了美觀處理了下
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
eyJpc3MiOiJsYWJzX3B1cmlmaWVyLWFwaS1wYW5lbCIsImlhdCI6MTU1Mjk3NTg3OCwiZXhwIjoxNTU1NTY3ODc4LCJhdWQiOiJodHRwOi8vZmYtbGFic19wdXJpZmllci1hcGktdGVzdC5mZW5kYS5pby9wcm9kL3YxL2F1dGgvand0Iiwic3ViIjoiMTUwMTM4NTYxMTg4NDcwNCIsInNjb3BlcyI6WyJyZWdpc3RlciIsIm9wZW4iLCJsb2dpbiIsInBhbmVsIl19.
m0HD1SUd30TWKuDQImwjIl9a-oWJreG7tKVzuGVh7e4
1.頭部(Header)
Header部分是一個json,描述JWT的元數據,通常是下面這樣
{
"alg": "HS256",
"typ": "JWT"
}
alg表示簽名使用的的算法,默認是HMAC SHA256,寫成HS256, tye表示這個token的類型,JWT token統一使用JWT,上面這段Header生成的token是
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
2.負載(Payload)
官方規定了7個字段,解釋如下
- iss: 簽發人,可以填寫生成這個token的ID等等,可選參數
- sub: 該JWT所面向的客戶,可以存儲用戶的account_id等等,可選
- aud:該JWTtoken的接收方,可以填寫生成這個token的接口URL,但是不強制,可選
- exp: 過期時間,時間戳,整數,可選參數
- iat:生成token的時間,unix時間,時間戳,可選參數
- nbf(Not Before): 表示該token在此時間前不可用,驗證不通過的意思,可選
- jti: JWT ID,主要用來生成一次性token,可選的參數
除了官方之外,我們還可以定義一部分自定義字段,但是考慮到BASE64是可逆的,所以不要放入敏感信息
下面是一個例子;
{
"iss": "labs_purifier-api-panel",
"iat": 1552975878,
"exp": 1555567878,
"aud": "http://ff-labs_purifier-api-test.fenda.io/prod/v1/auth/jwt",
"sub": "1501385611884704",
"scopes": [
"register",
"open",
"login",
"panel"
]
}
上面這個Payload,經過BASE64加密後,生成的token是
eyJpc3MiOiJsYWJzX3B1cmlmaWVyLWFwaS1wYW5lbCIsImlhdCI6MTU1Mjk3NTg3OCwiZXhwIjoxNTU1NTY3ODc4LCJhdWQiOiJodHRwOi8vZmYtbGFic19wdXJpZmllci1hcGktdGVzdC5mZW5kYS5pby9wcm9kL3YxL2F1dGgvand0Iiwic3ViIjoiMTUwMTM4NTYxMTg4NDcwNCIsInNjb3BlcyI6WyJyZWdpc3RlciIsIm9wZW4iLCJsb2dpbiIsInBhbmVsIl19
3.簽名(Signature)
Signature是對前面兩部分生成的兩段token的加密,使用的加密方式是Header裏面指定的,此處是HS256,此時,需要一個祕鑰,不可以泄露,大致過程如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
JWT的使用
JWT token 一般放在請求頭裏面,當然也可以放在cookie裏面,但是放在cookie裏面不可以跨域,例如:
Authorization: Bearer <token>
JWT在Python中的簡單生成和驗證
生成token
def create_token():
payload={
"iss": "labs_purifier-api-panel",
"iat": 1552975878,
"exp": 1555567878,
"aud": Config.AUDIENCE,
"sub": "1501385611884704",
"scopes": [
"register",
"open",
"login",
"panel"
]
}
token = jwt.encode(payload, Config.SECRET_KEY, algorithm='HS256')
return True, {'access_token': token}
驗證token
def verify_jwt_token(token):
try:
payload = jwt.decode(token, Config.SECRET_KEY,
audience=Config.AUDIENCE,
algorithms=['HS256'])
except (ExpiredSignatureError, DecodeError):
return False, token
if payload:
return True, jwt_model
需要注意的是,如果在生成的時候,加上了aud參數,驗證的時候也要用上audience參數,並且值必須一樣