jwt身份驗證

  http協議是無狀態協議,服務端不能從請求中判斷用戶的身份,用戶怎麼每次去找到自己對應的信息呢?

  1. cookie

  這種方式最簡單,在用戶第一次登陸成功某個網站A,網站A服務端就將你的用戶信息(比如用戶名,用戶id,證件號等等)寫入到cookie 對象中,然後再把這個cookie對象發送給對應的客戶端,客戶端就存下這個cookie,例如博客園的cookie如下

 

  當cookie超時時間到了瀏覽器就會自動刪除這個cookie,這個時候需要你重新登錄一下, 然後服務器就會根據你的用戶名和密碼去數據庫中查詢一次,成功查詢到就再一次將用戶信息丟到cookie對象中,返回給客戶端存起來,後續每次請求都帶着這個cookie

  這種方式的好處就是:用戶的所有信息都存在客戶端,服務端只有在數據庫中存了一份,服務端壓力很小;

  壞處是顯而易見,每次都要帶上這個cookie這麼多信息,一方面是傳輸效率問題,另一方面是安全問題,別人只要截獲你的cookie,你的所有信息都一覽無餘;

  還有一點就是有的客戶端會禁用cookie...

 

  2. session

  在cookie的基礎上優化了一下,因爲不是有安全和效率問題嗎,那麼我們就把用戶所有的信息都存到服務端,例如現在有這樣的一個結構:Map<sessionId,Session<User>>

  用戶第一次登陸成功,就會生成一個唯一字符串sessionId,然後將sessionId和用戶信息存到map中,最後就將這個sessionId丟到cookie返回給客戶端,後續的客戶端訪問服務端只需要帶着cookie,服務端就能從cookie中獲取到這個sessionId,到Map裏面去找,就可以找到用戶信息了;

  注意,不一定非要叫做sessionId這個名字啊,叫做aId,bId等等也行....看每個地方的要求

  這種方式比較安全,而且效率也提高了,因爲只需要多傳一個字符串,但是服務端內存中存所有的用戶信息,壓力都給到了服務端

  我們還從請求方式來比較cookie和session:

    cookie的方式一般只能用戶post請求,因爲get請求的url有長度限制

    session的方式只是get和post方式,get方式的話在url後面添加一個參數傳sessionId就行了,即使客戶端禁用了cookie,在服務端將sessionId傳給了客戶端之後,客戶端想辦法存起來下次請求的時候帶過去就行了

 

  3. session共享

  上面說的是單體應用的實現方式,但是到了分佈式環境下就會失效(很多東西在單機中使用是可以的,分佈式環境下就沒用了,比如數據庫事務,鎖),下圖所示,會導致tomcat2需要用戶重新登錄

 

  解決方案有兩種:

    1)hash一致性:在nginx中配置ip_hash,其實就是用過一定的算法對用戶的ip處理,假如用戶第一次訪問的是tomcat1,那麼只要用戶ip不會變化,第二次該用戶訪問的還是tomcat1

    2)引入中間件:這裏以redis爲例

 

4. jwt

  上面的實現方式看着一大堆東西也是麻煩,又是傳sessionId,又是引入redis,在分佈式環境下有沒有簡單的方式啊!

  jwt全稱JSON Web Token,我們之前每次都是傳的sessionId,這個字符串是沒有實際意義的,只是起到了一個唯一標識的作用,那麼有沒有可能我們把它的語義化呢?就是想辦法直接解析這個字符串,然後可以獲取用戶信息

  下圖所示,結構是不是一下子簡單多了,可以看到只要我們每次請求都帶上這個token,不管是單機環境,還是分佈式環境都適用,而且服務端也不需要保存什麼東西,客戶端只需要保存一個token字符串就行了;

 

  現在就比較關心的是jwt的那個算法和生成後的token字符串有什麼特殊的要求!

  token字符串的格式,分爲三部分,用點進行連接:aaa.bbb.ccc

示例:

 

  第一部分是Header:放入token的類型(“JWT”)和算法名稱(比如:HMAC SHA256或者RSA等等),然後使用Base64對這個JSON編碼就得到JWT的第一部分

 

  第二部分是Payload:一般放入用戶的不敏感信息,比如用戶id,名稱和角色等,即使被別人截獲了也沒啥用,然後使用Base64對這個JSON編碼就得到JWT的第二部分

 

  第三部分是Signature:準備一個只有你自己知道的密鑰,加上第一部分的字符串aaa和第二部分的字符串,通過Header中聲明的算法就生成了簽名,也就得到了第三部分

 

  將上面三部分通過點相連就組成了token,然後發到客戶端,客戶端只需要每次在請求頭中放入這個token,後端通過密鑰驗證這個token的合法性,並且從Payload中獲取用戶不敏感的信息,進行後續處理

  想看看簡單的demo,可以看看這個老哥的博客 ,不過一般校驗jwt是配置一個攔截器進行處理的

 

5. jwt的補充

  其實仔細想了想,一般還有以下兩個疑問

  1)Token被盜了怎麼辦?

      答: 在啓用https的情況下,token被放在Header中還是比較安全的。另外Token的有效期不要設置過長。例如可以設置爲1小時(微信公衆號的網頁開發的Token有效期爲2小時)。

      2)Token到期瞭如何處理?

     答:理論上Token過期應該是跳到登錄界面,但這樣太不友好了。可以在後臺根據Token的過期時間定期去請求新的Token。

可以看看以下兩篇博客看看

應用JWT進行用戶認證及Token的刷新

JWT生成token及過期處理方案

 

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