JWT 相關信息可參考: https://www.jianshu.com/p/576dbf44b2ae
DRF JWT 的使用方法:
1. 安裝 DRF JWT
# pip install djangorestframework-jwt
2. 配置
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES":("rest_framework_jwt.authentication.JSONWebTokenAuthentication",) # 全局設置的方法,也可在單個視圖中設置 }
3. 在 url 中添加相應路徑
from rest_framework.authtoken import views from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ re_path(r"^api-token-auth/",views.obtain_auth_token), # DRF 自帶的 token 認證模式;需導入 re_path(r"^login/",obtain_jwt_token), # jwt的認證接口(路徑可自定義任意命名) ]
4. 前端向 login/ 這個路徑發送請求時可進行登陸驗證;
5. 訪問需要登陸認證后才能訪問的url時,在請求頭(Header)中添加 Authorization:JWT <your_token> (Authorization 為 name,JWT <your_token> 為 value);登陸認證成功后,自動返回給前端一個 Token
6. 使用token訪問被保護的url
# 設置某些view的權限(permission_classes)為permissions.IsAuthenticated,那么沒有提供token而訪問被保護的view是不被允許的. # 你可以設置用戶注冊的權限為permissions.AllowAny,這樣用戶可以通過用戶名和密碼拿到token,在之后訪問被保護的view時,將token作為身份憑證發送給服務端(rest-framework會自動驗證token是否有效,如果在settings.py中做了准備中的配置的話)
7. JWT的額外設置(如過期時間)
# 在 settings 中 import datetime JWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300), # 設置 JWT Token 的有效時間 'JWT_AUTH_HEADER_PREFIX': 'JWT', # 設置 請求頭中的前綴 }
DRF JWT 文檔:http://getblimp.github.io/django-rest-framework-jwt/
注:認證的作用是取出當前用戶
自定制 jwt 的 Token
# 注冊成功后如果想讓前端自動登陸,則需要返回給前端一個 token;所以以下為手動生成一個 token 返回給前端 from rest_framework.mixins import CreateModelMixin from rest_framework_jwt.serializers import jwt_payload_handler,jwt_encode_handler class UserViewset(CreateModelMixin, viewsets.GenericViewSet): serializer_class = UserRegSerializer queryset = User.objects.all() # 用戶注冊成功后,會在 User 表中生成一條記錄;如果想要在生成 User記錄的同時,生成一個 token ,則需要重構 CreateModelMixin 的 create() 方法 def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user = self.perform_create(serializer) # 在此處生成 token res_dict = serializer.data payload = jwt_payload_handler(user) # user 是 User 表中生成的一條新記錄 res_dict["token"] = jwt_encode_handler(payload) # jwt_encode_handler(payload) 生成 token;並賦值給 res_dict["token"] # res_dict 還可以根據需要添加其它內容 headers = self.get_success_headers(serializer.data) return Response(res_dict, status=status.HTTP_201_CREATED, headers=headers) # 返回 res_dict def perform_create(self, serializer): return serializer.save() # 把保存的 User 對象返回
自定義Django的認證類:
settings.py
# 自定義用戶認證(如:手機號、郵箱登陸;Django的認證默認是只能通過用戶名和密碼認證) AUTHENTICATION_BACKENDS = ( "apps.users.views.CustomBackend", # 路徑.自定義認證類 )
views.py
from django.db.models import Q from django.contrib.auth.backends import ModelBackend from .models import UserInfo # Create your views here. class CustomBackend(ModelBackend): """ 自定義用戶認證(如:手機號、郵箱登陸) 自定義用戶認證時,需要把這個認證類放到 settings.py 中的 AUTHENTICATION_BACKENDS 中 """ def authenticate(self, request, username=None, password=None, **kwargs): # authenticate() 這個函數中處理認證的邏輯 """ :param request: :param username: 此時 username 可以是 用戶名 或者 手機號 :param password: :param kwargs: :return: """ try: user = UserInfo.objects.get(Q(username=username)|Q(mobile=username)) if user.check_password(password): # check_password() 時會轉化為密文的形式 return user except Exception as e: return None
DRF 緩存:
django的緩存在DRF中不能直接用,而應該用封閉后的緩存,如:rest_framework_extensions
1. 安裝 rest_framework_extensions
pip install drf-extensions
2. 配置 settings
REST_FRAMEWORK_EXTENSIONS = { 'DEFAULT_OBJECT_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_object_cache_key_func', # retrieve 方法 'DEFAULT_LIST_CACHE_KEY_FUNC': 'rest_framework_extensions.utils.default_list_cache_key_func', # list 方法 }
3. 在視圖中添加 緩存類 CacheResponseMixin
from rest_framework_extensions.cache.mixins import CacheResponseMixin class GoodsViewSet(CacheResponseMixin,mixins.ListModelMixin,mixins.RetrieveModelMixin,GenericViewSet): # 在對應視圖中添加 CacheResponseMixin(添加到第一個位置) """ 商品列表頁,分頁,過濾,搜索,排序 list: 所有商品列表 retrieve: 查看單個商品 """ queryset = Goods.objects.all().order_by("pk") serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend,filters.SearchFilter,filters.OrderingFilter) filter_class = GoodsFilter # 過濾 search_fields = ("name","goods_brief","goods_details") # 搜索 ordering_fields = ("sold_num","shop_price") # 排序 # 修改點擊數 def retrieve(self, request, *args, **kwargs): instance = self.get_object() # instance 是一個 Goods() 的對象 instance.click_num += 1 # 點擊數 +1 instance.save() serializer = self.get_serializer(instance) return Response(serializer.data)
4. 設置超時時間
REST_FRAMEWORK_EXTENSIONS = { 'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 15 # 表示15分鍾 }
注: 該緩存默認使用的是 自帶的 local memory cache(程序重啟緩存即消失)