drf JWT认证模块与自定制

   在djangorestframework中,有一款扩展模块可用于做JWT认证,使用如下命令进行安装:

pip install djangorestframework-jwt

   现在,就让我们开始使用它吧。

JWT配置

   该模块的所有配置都会从settings.py中进行读取,与drf一样,它会先去读取项目全局文件夹下的settings.py,再去读取自身的settings.py,所以如果我们要对JWT进行配置,则在项目全局文件夹下的settings.py中进行配置即可:

import datetime JWT_AUTH = { # 配置过期时间 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), # 配置请求头中携带token的前缀 'JWT_AUTH_HEADER_PREFIX': 'JWT', }

   如果你想了解更多配置,则可查看该模块读取的默认配置文件。

from rest_framework_jwt import settings

   在默认配置文件中,你可以看到如下代码,它会先去全局中找配置,再到局部中找配置:

USER_SETTINGS = getattr(settings, 'JWT_AUTH', None) auth组件

   下面将介绍如何使用auth组件与JWT配套使用,这当然非常方便,auth组件可以说是Django的核心。

   我打算这样做,对内置的user表做扩展,添加头像字段,只有用户登录后才能修改头像,否则将会采用默认头像。

准备工作

   首先我们需要对内置的auth_user表做扩展,如下所示:

from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): avatar = models.FileField(upload_to="avatar",default="avatar/default.png")

   其次配置上传文件的路径,声明media所在的位置,以及声明我们对内置的auth_user表做了扩展:

MEDIA_ROOT = BASE_DIR / "media" AUTH_USER_MODEL = "app01.User" # python manage.py makemigrations # python manage.py migrate

   最后打开资源暴露接口:

from django.contrib import admin from django.urls import path,re_path from django.views.static import serve from django.conf import settings urlpatterns = [ path('admin/', admin.site.urls), re_path(r"^media/(?P<path>.*)", serve, {"document_root": settings.MEDIA_ROOT}), ] 注册API

   现在,我们需要来做一个注册的API接口,如下所示:

class Register(ViewSet): def register(self,request,*args,**kwargs): serializer = UserModelSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(data=serializer.data,status=status.HTTP_201_CREATED) return Response(data=serializer.errors,status=status.HTTP_401_UNAUTHORIZED)

   我们可以规定register这个方法必须是POST请求才能访问,在url中进行配置(ViewSet是ViewSetMixin的子类,所以有actions参数):

path('register/', views.Register.as_view(actions={"post":"register"})),

   由于auth_user的密码需要密文,所以我们重写了模型序列化器的create方法。

from rest_framework import serializers from rest_framework.exceptions import ValidationError from app01 import models class UserModelSerializer(serializers.ModelSerializer): re_password = serializers.CharField(required=True, write_only=True) # 数据表中不存在该字段,我们自己写一个 class Meta: model = models.User fields = ("username","password","re_password","email") extra_kwargs = { "password":{"write_only":True} } def create(self, validated_data): password = validated_data.get("password") re_password = validated_data.get("re_password") email = validated_data.get("email") if re_password != password: raise ValidationError("两次密码输入不一致") if models.User.objects.filter(email=email): raise ValidationError("邮箱已被注册") validated_data.pop("re_password") # 删除即可,然后写入 user_obj = models.User.objects.create_user(**validated_data) # 加密创建 return user_obj 签发token

   下面将实现登录接口,如果你使用了auth组件作为扩展那么登录接口将十分的简单。

   JWT模块已经全部帮你完成了,你只需要向下面这么做:

from rest_framework_jwt.views import obtain_jwt_token # 导入视图,它都写好了的,并且会做验证 from rest_framework_jwt.views import ObtainJSONWebToken # 上面是一个变量,内部实际上是 obtain_jwt_token=ObtainJSONWebToken.as_view() urlpatterns = [ path('login/', obtain_jwt_token), # path('login/', ObtainJSONWebToken.as_view()), ]

   现在,当我们向该接口发送POST请求时,如果校验全部通过,则会发送给我们一个JWT

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjozLCJ1c2VybmFtZSI6Inl1bnlhIiwiZXhwIjoxNjA0NTYyMzcyLCJlbWFpbCI6IjIzMjNAcXEuY29tIn0._SmZ0e0mj5QVOKUftAwI3xBX4_BOw1ZNjAi94_U3mXg JWT认证

   下面我们来实现修改头像,头像必须先登录才能修改,所以要添加JWT认证。

from rest_framework.permissions import IsAuthenticated # 导入权限 from rest_framework_jwt.authentication import JSONWebTokenAuthentication # 导入认证 class SetAvatar(ViewSet): authentication_classes = [JSONWebTokenAuthentication] # 存储到request.user,如果只配置这个,则不登陆也能访问 permission_classes = [IsAuthenticated] # 必须已经登陆,即request.user不能是匿名用户 def set_avatar(self,request,*args,**kwargs): serializer = UserSetAvatar(instance=request.user,data=request.FILES) if serializer.is_valid(): serializer.save() return Response(data="修改成功",status=status.HTTP_205_RESET_CONTENT) return Response(data="修改失败",status=status.HTTP_401_UNAUTHORIZED)

   序列类如下:

class UserSetAvatar(serializers.ModelSerializer): class Meta: model = models.User fields = ("avatar",) extra_kwargs = { "avatar":{"write_only":True}, }

   url配置:

path('setavatar/', views.SetAvatar.as_view(actions={"post":"set_avatar"})),

   现在,我们使用POSTMAN来发送请求,首先要先登录,获得JWT:

  

image-20201105155846022

   然后需要在请求头中添加JWT认证,并且在body体中添加新头像:

   需要注意的是在添加JWT认证时,需要在VALUE处添加前缀JWT 随机字符串,以这样的格式提交,这是因为settings.py中设置了前缀。

  

image-20201105155937569

  

image-20201105155949700

   最后点击send,将会提示我们修改成功。

全局使用

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxyyp.html