JWT在身份認證方面的應用

JWT,Json web token。因爲在項目中準備應用,總結下,理清思路,希望對團隊有幫助。除簡介外,都融合了我個人的理解,不希望對別人產生誤導。網絡讓自媒體很容易,一定加以分析,全盤照收是很危險的;即使是讀書,也要分析,盡信書不如無書。

簡介

參考《jwt簡介》,我認爲很基礎,原文翻譯,比較客觀,就不重複了。

JWT應用場景?

簡介中提到兩個場景,我認爲主要第一種--身份認證。爲什麼採用這種方式呢?我總結了下

1、json格式簡單,相比xml,我更喜歡json;Self-contained,一般都翻譯成自包含,意思是jwt中已經有了你需要的全部信息,拿出來用就行。

2、同session相比,性能更好一些,省去了處理分佈session的問題;對於大行其道的restful來講,支持得很好;瀏覽器+app+pc,這種多終端開發,是很好的選擇。

如果可以,新系統不再使用session保存用戶信息。對於我們自己的platina開發平臺,可以平滑過渡到jwet,讓開發人員感覺不到。

JWT有什麼好處?

1、支持跨域訪問: Cookie是不允許垮域訪問的,這一點對Token機制是不存在的,前提是傳輸的用戶認證信息通過HTTP頭傳輸.

2、無狀態(也稱:服務端可擴展行):Token機制在服務端不需要存儲session信息,因爲Token 自身包含了所有登錄用戶的信息,只需要在客戶端的cookie或本地介質存儲狀態信息.

4、更適用CDN: 可以通過內容分發網絡請求你服務端的所有資料(如:javascript,HTML,圖片等),而你的服務端只要提供API即可.

5、去耦: 不需要綁定到一個特定的身份驗證方案。Token可以在任何地方生成,只要在你的API被調用的時候,你可以進行Token生成調用即可.

6、更適用於移動應用: 當你的客戶端是一個原生平臺(iOS, Android,Windows 8等)時,Cookie是不被支持的(你需要通過Cookie容器進行處理),這時採用Token認證機制就會簡單得多。

7、CSRF:因爲不再依賴於Cookie,所以你就不需要考慮對CSRF(跨站請求僞造)的防範。

8、性能: 一次網絡往返時間(通過數據庫查詢session信息)總比做一次HMACSHA256計算 的Token驗證和解析要費時得多.

9、不需要爲登錄頁面做特殊處理: 如果你使用Protractor 做功能測試的時候,不再需要爲登錄頁面做特殊處理.

10、基於標準化:你的API可以採用標準化的 JSON Web Token (JWT). 這個標準已經存在多個後端庫(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft).

流程

1、用戶認證。認證方式可能很多,自己認證或者sso。

2、認證後,服務器構造JWT。

3、把JWT返回客戶端,客戶端存儲。

4、客戶端訪問服務器,帶上JWT。

5、服務器端判斷JWT是否正確並且沒有超時,正常,向下流轉;否則,轉到授權。

服務器端

服務器端主要有2件事,我結合java說明下,j wt.io上介紹了幾個java類庫,根據個人喜好選擇。之前使用一個sso,用Nimbus,也支持jwt,但是他卻依賴net.minidev.json.JSONObject,就放棄了;後來採用jjwt,依賴jackson。

1、生成jwt

1.1、生成jwt的時機,認證之後,返回認證結果之前。

1.2、Payload(很多翻譯是直譯,對於理解沒有任何幫助)中如何設計屬性,這個對於可讀性比較重要。

根據JWT的標準,這些claims可以分爲以下三種類型:

a. Reserved claims(保留),它的含義就像是編程語言的保留字一樣,屬於JWT標準裏面規定的一些claim。JWT標準裏面定好的claim有:

iss(Issuser):代表這個JWT的簽發主體;

sub(Subject):代表這個JWT的主體,即它的所有人;

aud(Audience):代表這個JWT的接收對象;

exp(Expiration time):是一個時間戳,代表這個JWT的過期時間;

nbf(Not Before):是一個時間戳,代表這個JWT生效的開始時間,意味着在這個時間之前驗證JWT是會失敗的;

iat(Issued at):是一個時間戳,代表這個JWT的簽發時間;

jti(JWT ID):是JWT的唯一標識。

b. Public claims,略(不重要)

c. Private claims,這個指的就是自定義的claim。比如前面那個結構舉例中的admin和name都屬於自定的claim。這些claim跟JWT標準規定的claim區別在於:JWT規定的claim,JWT的接收方在拿到JWT之後,都知道怎麼對這些標準的claim進行驗證;而private claims不會驗證,除非明確告訴接收方要對這些claim進行驗證以及規則才行。

1.3、生成jwt的代碼

SecretKeySpec key = getKey();//getKey自己處理

Map claims = new HashMap();

claims.put("uid", userInfo.getAccountId()+"");

claims.put("user_name", userInfo.getUserName());

claims.put("nick_name",userInfo.getUserAttribute(PlatinaUser.NICK_NAME));

JwtBuilder builder = Jwts.builder()

.setClaims(claims)----一定先於下面的set方法,否則覆蓋。

.setIssuer("bmtech.com")

.setSubject(userInfo.getUserNum())

.setNotBefore(now)

.signWith(signatureAlgorithm, key);

return builder.compact();

2、處理jwt

Jwtjwt = Jwts.parser().setSigningKey(getKey()).parse(token);

Claims claims =  jwt.getBody();

客戶端

jwt存儲方式自己靈活掌握。

web:cookie/localStorage/sessionStorage/;

app:內存

安全

JWT是否安全?

既然jwt被很多大型公司採用,安全性一定是有保證的。

要保證私鑰的安全性,來保障簽名的安全。

有人提到jwt暴露簽名算法(alg),而且會有None(無簽名),所以建議隱去alg。一般的協議制定都會考慮擴展性和普適性。但是我們在應用中可以採用我們默認的算法,而不是根據alg去處理。

常見安全問題及處理?

1、XSS(Cross Site Script)

把token存儲在cookie中,同時設置httpOnly。

2、CSRF(cross-site request forgery)

2.1、判斷reffer。系統改動最小,通過filter就可以完成。

2.2、在參數中傳token。

2.3、通過header傳遞token。(推薦)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章