zoukankan      html  css  js  c++  java
  • 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(程序重启缓存即消失)

  • 相关阅读:
    能量最小化初探,graphcuts能量最小化调用
    【设计】B 端产品设计
    【产品分析】关于字节跳动的神话与现实
    【UI】数据表格设计
    【设计】交互文档结构
    【作品集】UX作品集
    【产品方法论】需求是怎么来的
    【ML】人脸识别
    【ML】DL的参数量计算
    【网站部署】flask
  • 原文地址:https://www.cnblogs.com/neozheng/p/9852888.html
Copyright © 2011-2022 走看看