八、DRF自帶使用者模組
阿新 • • 發佈:2020-10-22
DRF自帶使用者模組介面
原本為JWT開頭, 更改成Bearer, 單獨在setting中新增
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_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