1. 程式人生 > 實用技巧 >八、DRF自帶使用者模組

八、DRF自帶使用者模組

DRF自帶使用者模組介面
path('api/', include('rest_framework.urls'))
建立登陸的路徑 資料庫遷移後可以訪問 在pycharm中選擇Tools-Run manage.py檔案, 輸入createsuperuser進行建立使用者 在使用者模組的url中匯入from rest_framework_jwt.views import obtain_jwt_token檢視 再將路徑path('login/', obtain_jwt_token)新增到urlpatterns中 許可權設定 可以在需要許可權設定模組的view檢視檔案中新增, 或者直接在全域性setting中REST_FRAMEWORK配置, 對全域性有效
#只有登陸才可以訪問
permission_classes = [permissions.IsAuthenticated]
#不登入也可以訪問,這是預設的
permission_classes = [permissions.AllowAny]
#只有管理員才可以訪問
permission_classes = [permissions.IsAdmin]
#如果登陸了就都可以訪問,不登陸只能獲取資料,不能修改資料
permission_classes = [permissions.IsAuthenticatedOrReadOnly]

新增Session和Token認證 在全域性setting中REST_FRAMEWORK中配置 安裝jwt模組:pip install -i https://pypi.douban.com/simple djangorestframework-jwt 開啟跨域需要安裝:pip install -i https://pypi.douban.com/simple django-cors-headers
# 指定認證類(指定的是認證的方式)
'DEFAULT_AUTHENTICATION_CLASSES': [
    # token認證
    'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
    # DRF框架預設情況下,使用的是使用者會話認證(session)
    'rest_framework.authentication.SessionAuthentication',
    'rest_framework.authentication.BasicAuthentication',
]

Token認證更改字首
原本為JWT開頭, 更改成Bearer, 單獨在setting中新增
JWT_AUTH = {
    # 預設token的過期時間是五分鐘,這裡設定的是一天
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 修改token的字首,原來是JWT,修改為Bearer
    'JWT_AUTH_HEADER_PREFIX': 'Bearer',
    # 對token返回的資料進行重寫
    'JWT_RESPONSE_PAYLOAD_HANDLER':
        'utils.jwt_handler.jwt_response_payload_handler'
}
Session認證和Token認證的區別 Session認證的過程:   當用戶登陸成功後用戶會話資訊會儲存在後端資料庫, 存有SessionId, 過期時間等, 返回的響應頭中會有set-cookie欄位儲存SessionId, 當瀏覽器接收到響應頭中有set-cookie, 就會把裡面的SessionId取出來放在瀏覽器的cookie裡面, 那麼瀏覽器傳送請求時會攜帶這個SessionId, 後端接收到後會去資料庫校驗SessionId及是否過期 Session的特點:   資料儲存在服務端,會增加伺服器開銷   分散式架構中,難以維持Session會話同步   有CSRF攻擊風險 Token認證過程:   當用戶登陸成功後,會建立加密的Token令牌, 會把Token放在響應資料中返回給前端, 前端會存放在會話儲存或本地儲存中,會話儲存瀏覽器關掉以後就清空了,本地儲存瀏覽器關掉後還是存在的 Token特點:   儲存在客戶端   跨語言, 跨平臺(window,linux都適用)   拓展性強   鑑權效能高 Token的組成 由三部分組成:   頭部(header)     宣告型別     宣告加密演算法,預設為HS256     頭部採用base64加密,可以輕鬆解密,沒有安全性   載荷(payload)     存放過期時間,簽發使用者等     可以新增使用者的非敏感資訊     採用base64加密,可以輕鬆解密,沒有安全性   簽證(signaturn)     使用base64加密之後的header+.+使用base64加密之後的payload+使用HS256演算法加密,同時使用secret加鹽處理 增加Token的返回資訊 目前框架自帶的Token返回只有一個Token值,那麼假如有一個需求,需要返回Token的同時,返回使用者的使用者名稱和id,實現方法如下: 首先檢視原始碼,我們可以看到有一個jwt_response_payload_handler方法,token就是它返回的,那麼就可以重寫它(因為不止針對一個模組,所以可以把這個方法寫在公共模組內),重寫後如下:
def jwt_response_payload_handler(token, user=None, request=None):
    return {
        "token": token,
        'user_id': user.id,
        'user_name': user.username
    }

然後再把重寫後的方法寫在setting的JWT_AUTH中

'JWT_RESPONSE_PAYLOAD_HANDLER':
    'utils.jwt_handler.jwt_response_payload_handler'

實現註冊模組
class RegisterView(CreateAPIView):
    """
    註冊介面,因為CreateAPIView繼承了GenericAPIView,所以需要指定序列化器類和queryset查詢集
    但我們註冊只是建立,並沒做查詢,所以可以不用指定queryset
    """
    serializer_class = serializers.RegisterSerializer
因為CreateAPIView中繼承了CreateModelMixin,裡面有呼叫了serializer.save()方法,那麼會呼叫create方法,所以需要在serializer中實現

def create(self, validated_data):
    #因為在資料庫中無需儲存確認密碼,所以刪除確認密碼欄位
    validated_data.pop('password_confirm')
    # User模組可以使用create_user方法來建立使用者, 會對密碼進行加密
    user = User.objects.create_user(**validated_data)
    # 生成token返回
    jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
    jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
    payload = jwt_payload_handler(user)
    token = jwt_encode_handler(payload)
    user.token = token
    return user