DJANGO + JWT 令牌认证
Posted
技术标签:
【中文标题】DJANGO + JWT 令牌认证【英文标题】:DJANGO + JWT TOKEN AUTHENTICATION 【发布时间】:2020-10-24 09:46:12 【问题描述】:所以我试图为我的 android 应用程序构建一个后端。我正在尝试应用与 JWT 令牌一起使用的登录过程
这就是我所做的:
-
我已经制作了一个自定义用户模型。
自定义我的超级用户以获取电话号码和密码,而不是用户名和密码
我已成功创建超级用户并将其存储在我的数据库中(使用 postgreSQL)。
我还自定义了我的令牌声明和响应,如我的 LoginSerializer 类的 serializers.py 中所示。
但是,我做了之后遇到了一些问题:
-
现在,在自定义用户模型后,我无法使用新的自定义用户模型登录到 Django 管理,即使我已成功创建超级用户。
即使使用刚刚创建的成功超级用户帐户对令牌声明进行了自定义,我仍然无法获取令牌。
以下是一些错误信息:
以下是一些附件:
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser,BaseUserManager
from django.utils.translation import ugettext_lazy as _
from phone_field import PhoneField
class RegisterUserManager(BaseUserManager):
def create_user(self, phone_number,password):
if not phone_number:
raise ValueError('The phone number must be set')
user = self.model(
phone_number=phone_number,
password = password,)
user.save(using = self._db)
return user
def create_superuser(self,phone_number,password, **extra_fields):
user = self.create_user(
phone_number,
password = password
)
user.is_admin = True
user.save(using= self._db)
return user
class RegisterUser(AbstractBaseUser):
first_name = models.CharField(name = 'first_name',max_length=255,default = '')
last_name = models.CharField(name='last_name', max_length=255,default = '')
email = models.EmailField(name='email', max_length = 255)
phone_number = PhoneField(name='phone_number',unique=True)
birthday = models.DateField(name ='birthday',null= True)
nickname = models.CharField(max_length=100,name = 'nickname')
is_active = models.BooleanField(default = True)
is_admin = models.BooleanField(default= False)
last_login = models.DateTimeField(auto_now= True)
USERNAME_FIELD = 'phone_number'
REQUIRED_FIELDS = []
objects = RegisterUserManager()
def __str__(self):
return self.phone_number
def has_perm(self, perm, obj = None):
return True
def has_module_perms(self,perm,obj = None):
return True
@property
def is_staff(self):
return self.is_admin
views.py
from django.shortcuts import render
from django.http import HttpResponse,JsonResponse
from rest_framework.parsers import JSONParser
from restaccount.models import RegisterUser
# Login
from restaccount.serializers import RegisterSerializers,LoginSerializer
# LoginSerializers
from django.views.decorators.csrf import csrf_exempt
from rest_framework.generics import CreateAPIView
from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework.permissions import (AllowAny,IsAuthenticated)
# from rest_framework.generics import CreateAPIView
class RegisterView(CreateAPIView):
permission_classes = (AllowAny,)
serializer_class = RegisterSerializers
queryset = RegisterUser.objects.all()
class LoginView(TokenObtainPairView):
serializer_class = LoginSerializer
serializers.py
from rest_framework.serializers import (ModelSerializer,ValidationError)
from restaccount.models import RegisterUser
# Login
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
class RegisterSerializers(ModelSerializer):
class Meta:
model = RegisterUser
fields =['id',
'first_name',
'last_name',
'email',
'password',
'phone_number',
'nickname',
'birthday',
]
def create(self,validated_data):
first_name = validated_data['first_name']
last_name = validated_data['last_name']
email = validated_data['email']
password = validated_data['password']
phone_number = validated_data['phone_number']
nickname = validated_data['nickname']
birthday = validated_data['birthday']
user_obj = RegisterUser(
first_name = first_name,
last_name = last_name,
email = email,
password = password,
phone_number = phone_number,
nickname = nickname,
birthday = birthday,
)
user_obj.save()
return user_obj
def update(self, instance,validated_data):
instance.first_name = validated_data.get('first_name',instance.first_name)
instance.last_name = validated_data.get('last_name', instance.last_name)
instance.email = validated_data.get('email', instance.email)
instance.password = validated_data.get('password', instance.password)
instance.phone_number = validated_data.get('phone_number', instance.phone_number)
instance.nickname = validated_data.get('nickname', instance.nicknames)
instance.birthday = validated_data.get('birthday',instance.birthday)
instance.save()
return instance
def validate(self,data):
return data
def validate_phone_number(self,value):
phone_number = value
user_qs = RegisterUser.objects.filter(phone_number = phone_number)
if user_qs.exists():
raise ValidationError("This phone number is registered")
return value
class LoginSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls,user):
token = super().get_token(user)
token['phone_number'] = user.phone_number
token['password'] = user.password
return token
def validate(self,attrs):
data = super().validate(attrs)
refresh = self.get_token(self.user)
data['refresh'] = str(refresh)
data['access'] = str(refresh.access_token)
data['phone_number'] = self.user.phone_number
return data
【问题讨论】:
【参考方案1】:事实证明,模型中的密码字段必须经过哈希处理,使得 user.set_password(密码)。如果您想从 API 端点创建用户,这也是同样的情况。您必须将哈希密码存储在您的数据库中。
但是,我不知道为什么会这样。
【讨论】:
将密码保存为纯文本是一个严重的安全问题。如果您的数据库受到威胁,则可以假定用户帐户是安全的,因为散列密码是不可逆的。永远不要将密码保存为纯文本。以上是关于DJANGO + JWT 令牌认证的主要内容,如果未能解决你的问题,请参考以下文章