目錄python
router.register('register', views.RegisterViewSet, 'register') from rest_framework_jwt.views import ObtainJSONWebToken urlpatterns = [ url('^login/$', ObtainJSONWebToken.as_view()), url('', include(router.urls)) ]
from rest_framework.viewsets import GenericViewSet, ModelViewSet from rest_framework import mixins from . import models, serializers class RegisterViewSet(GenericViewSet, mixins.CreateModelMixin): queryset = models.User.objects.filter(is_active=True).all() serializer_class = serializers.RegisterSerializer
from rest_framework import serializers from rest_framework.exceptions import ValidationError from . import models class RegisterSerializer(serializers.ModelSerializer): re_password = serializers.CharField(write_only=True, min_length=8, max_length=18) class Meta: model = models.User fields = ('username', 'password', 're_password', 'mobile') extra_kwargs = { 'password': { 'write_only': True, 'min_length': 8, 'max_length': 18 } } # username和mobile能夠自定義局部鉤子校驗(省略) def validate(self, attrs): password = attrs.get('password') re_password = attrs.pop('re_password') if password != re_password: raise ValidationError({'re_password': 'password confirm error'}) return attrs # 須要重寫create,建立用戶須要密文 def create(self, validated_data): return models.User.objects.create_user(**validated_data)
調用寫好的登陸接口便可算法
from rest_framework_jwt.views import ObtainJSONWebToken urlpatterns = [ url('^login/$', ObtainJSONWebToken.as_view()), url('', include(router.urls)) ]
router.register('user/center', views.UserCenterViewSet, 'center')
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
''' AllowAny:遊客也可訪問 IsAuthenticated:必須登陸的用戶 纔有權限 IsAdminUser:必須登陸,而且時後臺用戶 纔有權限 IsAuthenticatedOrReadOnly:讀能夠(get請求能夠),可是寫(post請求)必須登陸 '''
class UserCenterSerializer(serializers.ModelSerializer): class Meta: model = models.User fields = ('username', 'mobile', 'icon', 'email')
router.register('books', views.BookViewSet, 'book')
class BookViewSet(ModelViewSet): queryset = models.Book.objects.all() serializer_class = serializers.BookSerializer
class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = ('name', )
""" 1)認證規則 2)如何自定義認證類 3)咱們通常不須要自定義認證類,在settings中全局配置第三方 jwt 認證組件提供的認證類便可 """
""" 1)自定義認證類,繼承 BaseAuthentication 類 2)必須重寫 authenticate(self, request) 方法 沒有認證信息,返回None:匿名用戶(遊客) => 匿名用戶request.user也有值,就是"匿名對象(Anonymous)" 有認證信息,且經過,返回(user, token):合法用戶 => user對象會存到request.user中 有認證信息,不經過,拋異常:非法用戶 """
""" 1)權限規則 2)如何自定義權限類 3)咱們通常在視圖類中局部配置drf提供的權限類,可是也會自定義權限類完成局部配置 """
""" 1)自定義權限類,繼承 BasePermission 類 2)必須重寫 has_permission(self, request, view): 方法 設置權限條件,條件經過,返回True:有權限 設置權限條件,條件失敗,返回False:有權限 3)drf提供的權限類: AllowAny:匿名與合法用戶均可以 IsAuthenticated:必須登陸,只有合法用戶能夠 IsAdminUser:必須是admin後臺用戶 IsAuthenticatedOrReadOnly:匿名只讀(get請求能夠)(post請求不能夠),合法用戶無限制 """
""" jwt優點 1)沒有數據庫寫操做,高效 2)服務器不存token,低耗 3)簽發校驗都是算法,集羣 """
""" 1)jwt分三段式:頭.體.簽名 (head.payload.sgin) 2)頭和體是可逆加密,讓服務器能夠反解出user對象;簽名是不可逆加密,保證整個token的安全性的 3)頭體簽名三部分,都是採用json格式的字符串,進行加密,可逆加密通常採用base64算法,不可逆加密通常採用hash(md5)算法 4)頭中的內容是基本信息:公司信息、項目組信息、token採用的加密方式信息 { "company": "公司信息", ... } 5)體中的內容是關鍵信息:用戶主鍵、用戶名、簽發時客戶端信息(設備號、地址)、過時時間 { "user_id": 1, ... } 6)簽名中的內容時安全信息:頭的加密結果 + 體的加密結果 + 服務器不對外公開的安全碼 進行md5加密 { "head": "頭的加密字符串", "payload": "體的加密字符串", "secret_key": "安全碼" } """
""" 1)用基本信息存儲json字典,採用base64算法加密獲得 頭字符串 2)用關鍵信息存儲json字典,採用base64算法加密獲得 體字符串 3)用頭、體加密字符串再加安全碼信息存儲json字典,採用hash md5算法加密獲得 簽名字符串 帳號密碼就能根據User表獲得user對象,造成的三段字符串用 . 拼接成token返回給前臺 """
""" 1)將token按 . 拆分爲三段字符串,第一段 頭加密字符串 通常不須要作任何處理 2)第二段 體加密字符串,要反解出用戶主鍵,經過主鍵從User表中就能獲得登陸用戶,過時時間和設備信息都是安全信息,確保token沒過時,且時同一設備來的 3)再用 第一段 + 第二段 + 服務器安全碼 不可逆md5加密,與第三段 簽名字符串 進行碰撞校驗,經過後才能表明第二段校驗獲得的user對象就是合法的登陸用戶 """
""" 1)用帳號密碼訪問登陸接口,登陸接口邏輯中調用 簽發token 算法,獲得token,返回給客戶端,客戶端本身存到cookies中 2)校驗token的算法應該寫在認證類中(在認證類中調用),全局配置給認證組件,全部視圖類請求,都會進行認證校驗,因此請求帶了token,就會反解出user對象,在視圖類中用request.user就能訪問登陸的用戶 注:登陸接口須要作 認證 + 權限 兩個局部禁用 """
>: pip install djangorestframework-jwt
(登陸接口):視圖類已經寫好了,配置一下路由就行(urls.py)數據庫
from rest_framework_jwt.views import ObtainJSONWebToken # api/urls.py urlpatterns = [ # ... url('^login/$', ObtainJSONWebToken.as_view()), ] # Postman請求:/api/login/,提供username和password便可
認證類已經寫好了,全局配置一下認證組件就好了(settings.py)django
# 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': [], }
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": "你的密碼"} 訪問 /api/login/ 接口等到 token 字符串 2)在請求頭用 Authorization 攜帶 "jwt 登陸獲得的token" 訪問 /api/user/center/1/ 接口訪問我的中心 """