最近在作一個審覈系統,後臺登陸用到JWT登陸認證,在此主要作個總結git
Json web token (JWT), 根據官網的定義,是爲了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標準.該token被設計爲緊湊且安全的,特別適用於分佈式站點的單點登陸場景。JWT的聲明通常被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便於從資源服務器獲取資源,也能夠增長一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用於認證,也可被加密。github
此處主要和傳統的session做對比,傳統的session在服務器端須要保存一些登陸信息,一般是在內存中,在後端服務器是集羣等分佈式的狀況下,其餘主機沒有保存這些信息,因此都須要經過一個固定的主機進行驗證,若是用戶量大,在認證這個點上容易造成瓶頸,是應用不易拓展。web
JWT由三個部分組成,用點號分割,看起來像是這樣,JWT token自己沒有空格換行等,下面是爲了美觀處理了下算法
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9. eyJpc3MiOiJsYWJzX3B1cmlmaWVyLWFwaS1wYW5lbCIsImlhdCI6MTU1Mjk3NTg3OCwiZXhwIjoxNTU1NTY3ODc4LCJhdWQiOiJodHRwOi8vZmYtbGFic19wdXJpZmllci1hcGktdGVzdC5mZW5kYS5pby9wcm9kL3YxL2F1dGgvand0Iiwic3ViIjoiMTUwMTM4NTYxMTg4NDcwNCIsInNjb3BlcyI6WyJyZWdpc3RlciIsIm9wZW4iLCJsb2dpbiIsInBhbmVsIl19. m0HD1SUd30TWKuDQImwjIl9a-oWJreG7tKVzuGVh7e4
Header部分是一個json,描述JWT的元數據,一般是下面這樣json
{ "alg": "HS256", "typ": "JWT" }
alg表示簽名使用的的算法,默認是HMAC SHA256,寫成HS256, tye表示這個token的類型,JWT token統一使用JWT,上面這段Header生成的token是後端
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
官方規定了7個字段,解釋以下api
除了官方以外,咱們還能夠定義一部分自定義字段,可是考慮到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
Signature是對前面兩部分生成的兩段token的加密,使用的加密方式是Header裏面指定的,此處是HS256,此時,須要一個祕鑰,不能夠泄露,大體過程以下:服務器
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT token 通常放在請求頭裏面,固然也能夠放在cookie裏面,可是放在cookie裏面不能夠跨域,例如:
Authorization: Bearer <token>
生成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參數,而且值必須同樣