JWT的组成:三部分组成 header部分:JWT的类型和加密算法
payload部分:JWT的签发者、JWT的接收者、JWT的持续时间,以及一些用户非敏感信息
signatrue部分:签名部分是由Header和Payload组合而成,将Header和Claim这两个Json分别使用Base64方式进行编码,生成字符串Header和Payload,然后将Header和Payload以Header.Payload的格式组合在一起形成一个字符串,然后使用上面定义好的加密算法和一个密匙(这个密匙存放在服务器上,用于进行验证)对这个字符串进行加密,形成一个新的字符串,这个字符串就是Signature
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token),
]
创建一个超级管理员:python manage.py createsuperuser
会在表auth_user中创建一条数据:
调用登录接口
返回数据中只有token,要是想要返回其它数据,则重写jwt_response_payload_handler方法
def jwt_response_payload_handler(token, user=None, request=None):
return {
'user_id': user.id,
'username': user.username,
'token': token
}
然后,在全局settings中配置引用
JWT_AUTH = {
# JWT响应处理器
'JWT_RESPONSE_PAYLOAD_HANDLER':'utils.jwt_handle.jwt_response_payload_handler',
# 'JWT_RESPONSE_PAYLOAD_HANDLER':'rest_framework_jwt.utils.jwt_response_payload_handler',
# jwt前缀
'JWT_AUTH_HEADER_PREFIX': 'JWT',
# 到期时间
'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
}
REST_FRAMEWORK={
...
...
...
# 全局的认证方式
'DEFAULT_AUTHENTICATION_CLASSES': [
# token认证
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
# 使用账号密码认证
'rest_framework.authentication.BasicAuthentication'
],
# 全局的权限配置
'DEFAULT_PERMISSION_CLASSES': [
# 默认是所有权限
# 'rest_framework.permissions.AllowAny',
# 只有登录用户才可以访问接口
'rest_framework.permissions.IsAuthenticated',
# 只有超级管理员才可以访问
# 'rest_framework.permissions.IsAdminUser'
# 如果没登录,只能获取数据,如果登录成功,就具备任意权限
# 'rest_framework.permissions.IsAuthenticatedOrReadOnly'
],
}
在users中的serializers.py中
from rest_framework import serializers,validators
from django.contrib.auth.models import User
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
class RegisterSerializer(serializers.ModelSerializer):
password_confirm = serializers.CharField(label='确认密码', help_text='确认密码',
min_length=6, max_length=20,
write_only=True,
error_messages={
'min_length': '仅允许6~20个字符的确认密码',
'max_length': '仅允许6~20个字符的确认密码', })
token = serializers.CharField(label='生成token', read_only=True)
class Meta:
model = User
fields = ('id', 'username', 'password', 'email', 'password_confirm', 'token')
extra_kwargs = {
'username': {
'label': '用户名',
'help_text': '用户名',
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的用户名',
'max_length': '仅允许6-20个字符的用户名',
}
},
'email': {
'label': '邮箱',
'help_text': '邮箱',
'write_only': True,
'required': True,
# 添加邮箱重复校验
'validators': [validators.UniqueValidator(queryset=User.objects.all(), message='此邮箱已注册')],
},
'password': {
'label': '密码',
'help_text': '密码',
'write_only': True,
'min_length': 6,
'max_length': 20,
'error_messages': {
'min_length': '仅允许6-20个字符的密码',
'max_length': '仅允许6-20个字符的密码',
}
}
}
# 多字段校验:直接使用validate,但是必须返回attrs
def validate(self, attrs):
if attrs.get('password') != attrs.get('password_confirm'):
raise serializers.ValidationError('密码与确认密码不一致')
return attrs
def create(self, validated_data):
validated_data.pop('password_confirm')
# 创建user模型对象
user = User.objects.create_user(**validated_data)
# 创建token
payload = jwt_payload_handler(user)
token = jwt_encode_handler(payload)
user.token = token
return user
users/views.py中
注意需要指定permission_classes = []为空列表或者允许所有权限[rest_framework.permissions.AllowAny],因为此接口不需要任何认证就可访问
from rest_framework import generics
from users.serializers import RegisterSerializer
class UserView(generics.CreateAPIView):
serializer_class = RegisterSerializer
# 注意需要指定permission_classes = []为空列表或者允许所有权限[rest_framework.permissions.AllowAny]
permission_classes = []
users/urls.py中
from django.urls import path,include
from rest_framework_jwt.views import obtain_jwt_token
from .views import UserView
urlpatterns = [
path('login/', obtain_jwt_token),
path('register/',UserView.as_view())
]