DRF JWT的用法 & Django的自定义认证类 & DRF 缓存

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(程序重启缓存即消失)

 

posted @ 2018-10-25 21:06  neozheng  阅读(4697)  评论(0编辑  收藏  举报