三大認證組件及jwt認證規則

三大認證組件及jwt認證規則

一、認證組件

一、認證規則

  1. 從請求頭中(Authorization)獲取認證信息(token)算法

  2. 若是沒有拿到認證信息,直接斷定該請求爲匿名請求(遊客) => 表明認證經過了,返回None數據庫

  3. 若是拿到認證信息,進行信息校驗,校驗成功會獲得請求對象(用戶) => 表明認證經過了,認證方法返回元組(user, token)django

  4. 若是拿到的認證信息,進行信息校驗,校驗失敗了,就拋出異常json

  5. 通常認證組件在settings中進行全局配置api

二、自定義認證類

咱們通常都不須要自定義認證類,在settings中全局配置第三方 jwt 認證組件提供的認證類便可,若是要自定義認證類步驟以下:安全

  1. 自定義認證類,首先繼承 BaseAuthentication 類服務器

  2. 必須重寫 authenticate(self, request) 方法cookie

    • 沒有認證信息,返回None:匿名用戶(遊客) => 匿名用戶request.user也有值,就是"匿名對象(Anonymous)"session

    • 有認證信息,且經過,返回(user, token):合法用戶 => user對象會存到request.user中框架

    • 有認證信息,不經過,拋異常:非法用戶

二、權限組件

一、權限規則

  1. 權限組件只有在認證經過後,再會執行,權限組件的目的就是判斷認證經過的用戶(匿名用戶、有權限用戶)

  2. 權限規則其實就是條件邏輯,有權限就返回True => 表明權限經過

  3. 條件邏輯判斷失敗,表明用戶沒有權限,返回False => 權限失敗

  4. 權限組件通知在視圖類中局部配置

二、自定義權限類

咱們通常在視圖類中局部配置drf提供的權限類,可是也會自定義權限類完成局部配置

  1. 自定義權限類,首先繼承 BasePermission 類

  2. 必須重寫 has_permission(self, request, view): 方法

    • 設置權限條件,條件經過,返回True => 有權限

    • 設置權限條件,條件不經過,返回False => 沒有權限

  3. drf提供的權限類:

    • AllowAny:匿名與合法用戶均可以

    • IsAuthenticated:必須登陸,只有合法用戶能夠

    • IsAdminUser:必須是admin後臺用戶

    • IsAuthenticatedOrReadOnly:匿名只讀,合法用戶無限制

from rest_framework.permissions import AllowAny, IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly
class UserCenterViewSet(GenericViewSet, mixins.RetrieveModelMixin):
    permission_classes = [IsAuthenticated, ]
​
    queryset = models.User.objects.filter(is_active=True).all()
    serializer_class = serializers.UserCenterSerializer

三、jwt認證示意圖

一、jwt優勢:

  1. 沒有數據庫寫操做 => 高效

  1. 服務器不存在token => 低耗

  1. 簽發校驗都是算法 => 集羣

二、基於session的認證(通常不使用)

三、基於session認證下的集羣部署

四、基於jwt的認證

五、基於jwt認證下的服務器集羣

四、jwt認證算法:簽發與校驗

一、jwt分三段式:頭.體.簽名 (head.payload.sign)

二、頭和體是可逆加密,讓服務器能夠反解出user對象;簽名是不可逆加密,保證整個token的安全性

三、頭.體.簽名三部分,都是採用json格式的字符串進行加密,可逆加密通常採用base64算法,不可逆加密通常採用hash(md5)算法

四、頭中的內容是基本信息:公司信息、項目組信息、token採用的加密方式信息(通常不會變)

五、體中的內容是關鍵性信息:用戶主鍵、用戶名、簽發是客戶端信息(設備號、地址)、過時時間

六、簽名中的內容是安全信息:頭的加密結果+體的加密結果+服務器不對外公開的安全碼,進行 md5 加密,{"head":"頭的加密字符串","payload":"體的加密字符串","secret_key": "安全碼"}

一、簽發:根據登陸請求提交的帳號+密碼+設備信息 簽發token

  1. 用基本信息存儲json字典,採用base64算法加密獲得 頭字符串

  2. 用關鍵信息存儲json字典,採用base64算法加密獲得 體字符串

  3. 用頭加密字符串+體加密字符串+安全碼信息存儲json字典,採用hash md5算法加密獲得 簽名字符串

帳戶密碼就能根據User表獲得user對象,造成的三段字符串用 . 拼接成token返回給前臺

二、校驗:根據客戶端帶token的請求 反解出 user 對象

  1. 將token按 . 拆分爲三段字符串,第一段:頭加密字符串,通常不須要作任何處理

  2. 第二段:體加密字符串,要反解出用戶主鍵,經過主鍵從User表中就能獲得登陸用戶,過時時間和設備信息都是安全信息,確保token沒過時,且同一個設備來的

  3. 再用 第一段+第二段+服務器安全碼 不可逆md5加密,與第三段簽名字符串進行對比校驗,經過後才能表明第二段校驗的user對象是合法用戶

五、drf項目的jwt認證開發流程

  1. 用帳號密碼訪問登陸接口,登陸接口邏輯中調用 簽發token算法,獲得token,返回給客戶端,客戶端本身存到cookies中

  2. 校驗token的算法應該寫在認證類中(在認證類中調用),全局配置給認證組件,全部視圖類請求,都會進行認證校驗,因此請求帶了token,就會反解出user對象,在視圖類中用request.user就能訪問登陸的用戶

注:登陸接口須要作認證+權限兩個局部禁用

六、drf-jwt框架基本使用

一、安裝

pip install djangorestframework-jwt

二、簽發token(登陸接口):視圖類已經寫好,配置一下路由就行(urls.py)

# api/urls.py
urlpatterns = [
     ...
    url('^login/$', ObtainJSONWebToken.as_view()),
]
​
# Postman請求:/api/login/,提供username和password便可

三、校驗token(認證組件):認證類已經寫好了,全局配置一下認證組件就好了(settings.py)

# drf-jwt的配置
import datetime
JWT_AUTH = {
    # 配置過時時間
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
}
​
​
# drf配置(把配置放在最下方)
REST_FRAMEWORK = {
    # 自定義三大認證配置類們
    'DEFAULT_AUTHENTICATION_CLASSES': ['rest_framework_jwt.authentication.JSONWebTokenAuthentication'],
    # 'DEFAULT_PERMISSION_CLASSES': [],
    # 'DEFAULT_THROTTLE_CLASSES': [],
}

四、設置須要登陸才能訪問的接口進行測試(views.py)

from rest_framework.permissions import IsAuthenticated
class UserCenterViewSet(GenericViewSet, mixins.RetrieveModelMixin):
    # 設置必須登陸才能訪問的權限類
    permission_classes = [IsAuthenticated, ]
​
    queryset = models.User.objects.filter(is_active=True).all()
    serializer_class = serializers.UserCenterSerializer

測試:

1)用 {"username": "你的用戶", "password": "你的密碼"} 訪問 post請求 /api/login/ 接口拿到 token 字符串

2)在請求頭用 Authorization 攜帶 "jwt 登陸獲得的token" 訪問 get請求 /api/user/center/1/ 接口訪問我的中心
相關文章
相關標籤/搜索