jwt身份驗證

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

  1. cookienginx

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

 

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

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

  壞處是顯而易見,每次都要帶上這個cookie這麼多信息,一方面是傳輸效率問題,另外一方面是安全問題,別人只要截獲你的cookie,你的全部信息都盡收眼底;後端

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

 

  2. sessiontomcat

  在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及過時處理方案

相關文章
相關標籤/搜索