1. 程式人生 > >JWT登入原理及使用

JWT登入原理及使用

一、JWT原理:

  參考文章:https://www.jianshu.com/p/180a870a308a

  1、傳統的登入方式:

    瀏覽器輸入使用者名稱密碼,服務端校驗通過,根據使用者資訊生成一個token,將token和user_id存到資料庫或者session中,並將token返回給前端,存入cookie,後面瀏覽器每次請求都會帶上cookie,服務端根據cookie查詢使用者,驗證使用者有效性。

    弊端:

      1)如果出現XSS(跨站指令碼攻擊)漏洞,由於cookie可以被js讀取,XSS漏洞會導致使用者token被洩露。

       解決方案:

        a)設定httpOnly,這樣的話cookie將不會被js讀取,瀏覽器會自動將它加到請求頭資訊中,但是帶來了新的問題,很容易被XSRF(跨站請求偽造)攻擊,因為只要當前瀏覽器開著,另一個介面可以很容易的跨站請求這個介面的內容,因為cookie會被預設傳送出去。

        b)設定secure,這樣cookie就只能通過https傳輸,可以過濾掉一些使用http協議請求的XSS注入。

      2)將驗證資訊存到資料庫中,每次驗證的時候,都需要去資料庫中查詢,增加了資料庫的查詢和儲存開銷。

      3)如果將token存到session中,也會增加伺服器的儲存壓力。

  2、為什麼使用 JWT

    1)可以通過URL POST引數或者http header中傳送,資料量小,傳輸速度快。

    2)自包含:負載中包含了使用者所需要的所有資訊,避免多次查詢資料庫。

    3)JWT組成:

      header+payload+signature 三者通過點【.】連線起來就是JWT了。

      

 

      a)header頭部:包含token型別和採用的加密演算法

        {"alg":"HS256", "typ":"JWT"}

      b)payload負載:存放資訊的地方,可以把使用者ID等資訊存放在payload中。

        常用的資訊有:iss(簽發者), exp(過期時間), sub(面向使用者), aud(接收方), iat(簽發時間)等。

      c)signature簽名:使用編碼後(base64編碼)的header和payload再加上我們提供的一個公鑰,然後使用header中指定的簽名演算法進行簽名。作用是保證JWT沒有被竄改過。

      JWT只適合向web端傳遞一些非敏感資訊,因為base64編碼是可逆的,很容易被破解。

      JWT通常用來設計使用者認證和授權系統,還有我們通常說的單點登入等。

 

二、JWT的使用過程

        

  1)前端通過表單將使用者名稱和密碼傳送到後端介面。

  2)後端核對使用者名稱和密碼後,將使用者的id及其他非敏感資訊作為JWT Payload,將其與頭部分別進行base64編碼後簽名,生成JWT

  3)後端將JWT字串作為登入成功的結果返回給前端,前端可以將JWT存到localStorage或者sessionStorage中,退出登入時,前端刪除儲存的JWT資訊即可。

  4)前端每次在請求時,將JWT放到header中的Authorization

  5)後端驗證JWT的有效性

  6)驗證通過後,進行其他邏輯操作。

 

三、JWT使用方法:

  1、安裝

    pip install djangorestframework-jwt

  2、將JSONWebTokenAuthentication加到settings.py中的DEFAULT_AUTHENTICATION_CLASSES中,它可以將使用者post過來的資料進行驗證,並將user取出來,它和MIDDLEWARE中的AuthenticationMiddleware的原理是一樣的。

    

  3、配置JWT的認證介面的url

    from djangorestframework-jwt.views import obtain_jwt_token

    url(r"^login$", obtain_jwt_token)

  4、前端訪問 login,傳入使用者名稱和密碼,伺服器會給瀏覽器返回一段token(jwt)

    {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJleHAiOjE1MzEzNzU4NjEsImVtYWlsIjoiMzcwMTkzNTkzQHFxLmNvbSIsInVzZXJuYW1lIjoiYWRtaW4ifQ.BIl1b68VV-LvZOu-wrUeMxUFI3IREapgqfbTtzB6Ftw"}

  5、在後面的請求中,將JWT token資訊 加入到header中的authorization中。

  6、擴充套件:

    DRF預設是通過郵箱作為使用者名稱來登入的,所以如果我們是通過手機或者其他方式登入的話,需要重寫DRF的認證方式。

    from django.db.models import Q

    from django.contrib.auth.backends import ModelBackend

    from django.contrib.auth import get_user_model

    User = get_user_model()

    class CustomBackend(ModelBackend):

      def authenticate(self, request, username=None, password=None, **kwargs):

        try:

          user = User.objects.get(Q(username=username) | Q(mobil = username))

          if user.check_password(password):

            return user

          else:

            return None

 

 

        except Exception as e:

          return None

   7、將重寫的CustomBackend加入到settings中

    

  8、JWT的額外設定: