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(程序重启缓存即消失)
Code your future.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端