Web API與JWT認證

​JWT(Json Web Token)定義了一種使用Json形式在網絡間安全地傳遞信息的簡潔開放的標準(RFC 7519)。JWT使用數字簽名確保信息是可信的。

1、Session認證和Token認證
Http協議自己是無狀態的,若是用戶向服務器傳遞了用戶名和密碼進行了用戶認證,那麼下一次請求時用戶仍是須要進行一樣的認證,由於根據Http協議,咱們沒法知道請求是由哪一個用戶發出的。因此,爲了能識別哪一個用戶,免去每次都進行驗證的麻煩,就有了傳統的Session認證和token認證方案。

a) Session認證
Session認證的方案爲:第一次用戶認證請求經過時,服務器端存儲用戶的登陸信息,而後在響應時傳遞給瀏覽器,瀏覽器保存爲cookie,下次請求時把cookie發送給服務器,服務器根據cookie信息來識別是哪一個用戶。
Session認證適用於單個服務器的場合,若是用戶增多,須要部署多個服務器時,Session認證就會暴露問題。由於每一個用戶在認證後,服務器都會記錄Session,通常保存在內存中,隨着認證用戶增多,服務器開銷也會增大;並且認證用戶的後續請求都須要到這臺保存了本身Session的服務器上驗證Cookie。在多集羣分佈式的場合,這就形成了性能瓶頸,對負載均衡、應用的擴展都會形成影響。
進程外Session經過將Session保存在數據庫或硬盤中能夠解決服務器內存開銷的問題,但仍然不便於擴展。

b) Token認證
Token認證也是無狀態的,不須要在服務端保存認證用戶的信息,它的認證流程爲:用戶使用用戶名密碼請求服務器;服務器驗證用戶,若是驗證經過就發給用戶一個token;客戶端保存token,並在以後的每次請求都附上token;服務端驗證token、返回數據。
Token認證機制不須要保存認證用戶的信息、也不須要考錄用戶在那臺服務器登陸,能夠很好地適應應用的擴展。
token的體積很小,請求服務端時,能夠被附在URL、Header或是Post參數中。並且token中包含了用戶相關的必要、非私密的相信,免去了服務端再次查詢數據庫的開銷。html

 

c) JWT的使用場景算法

最經常使用於對已經登陸用戶的認證,好比單點登陸,只需在每次請求中都附上JWT,JWT體積小巧且支持跨域、多語言。
JWT也能夠用於信息傳輸,由於有根據payload和header計算出的簽名的保護,能夠確保傳遞的信息不被篡改。

3、JWT的構成
JWT由Header、Payload、Signature三部分構成,之間用點號風格,構成xx.yy.zz的形式。
a) Header聲明瞭token類型、算法類型(HMAC SHA256或RSA),好比
{
  "alg": "HS256",
  "typ": "JWT"
}
而後對header作Base64URL編碼。
b) Payload中保存了聲明信息,聲明信息有標準聲明、公開聲明、自定義聲明三種類型,前兩種聲明在相關的標準中已經規定https://www.iana.org/assignments/jwt/jwt.xhtml,推薦但不強制使用,標準聲明舉例有:

iss: jwt簽發者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過時時間,這個過時時間必需要大於簽發時間
nbf: 定義在什麼時間以前,該jwt都是不可用的.
iat: jwt的簽發時間
jti: jwt的惟一身份標識,主要用來做爲一次性token,從而回避重放攻擊
發送方和接收方也能夠自定聲明。
{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
載荷信息也使用Base64URL編碼。


c) Signature,簽證信息是根據Header、Payload的Base64URL編碼以及密鑰(Secret)加密生成的,加密算法使用header中定義的類型。

d) Secret信息只保存在服務端,服務端爲客戶端簽發jwt token要使用Secret,後續對客戶端遞交的jwt的驗證也要使用Secret,因此必定要防止Secret的泄露。

4、JWT的使用數據庫

var secret = "h3h5k9kll789";
//JWT簽發
var payload = new Dictionary<string, object>
{
  { "UserID",123},
  {"UserName","admin" }
};
//指定HMAC加密算法
IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
IJsonSerializer serializer = new JsonNetSerializer();
IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
IJwtEncoder encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
var token = encoder.Encode(payload, secret);

//JWT驗證及解析
IJsonSerializer serializer1 = new JsonNetSerializer();
IDateTimeProvider provider1 = new UtcDateTimeProvider();
IJwtValidator validator1 = new JwtValidator(serializer1, provider1);
IBase64UrlEncoder urlEncoder1 = new JwtBase64UrlEncoder();
IJwtDecoder decoder = new JwtDecoder(serializer1, validator1, urlEncoder1);
//解析出PayLoad
var json = decoder.Decode(token, secret, verify: true);json



學習資料:如鵬網.net提升班http://www.rupeng.com/News/10/4603.shtml
http://www.jianshu.com/p/576dbf44b2ae
https://jwt.io/跨域

相關文章
相關標籤/搜索