我有自定义用户模型并创建了自定义身份验证后端。我使用django rest framework和django rest framework JWT进行令牌身份验证。
用户模型:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
unique=True,
max_length=254,
)
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=15)
mobile = models.IntegerField(unique=True)
date_joined = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name', 'mobile']
Auth后端:
class EmailOrMobileAuthBackend(object):
def authenticate(self, username=None, password=None):
try:
user = get_user_model().objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
if username.isdigit():
try:
user = get_user_model().objects.get(mobile=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
else:
return None
def get_user(self, user_id):
try:
return get_user_model().objects.get(pk=user_id)
except User.DoesNotExist:
return None
并已在settings.py中添加:
AUTHENTICATION_BACKENDS = ('accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',)
登录django管理站点时,电子邮件和手机号码都可以正常验证用户身份。但是,当我尝试使用django rest framework JWT为用户获取令牌时,出现错误:
curl -X POST -d "email=admin@gmail.com&password=123123" http://localhost/api-token-auth/
"non_field_errors": [
"Unable to log in with provided credentials."
]
我还在Rest身份验证默认身份验证框架中添加了自定义身份验证后端类,但它仍无效:
REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
'accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
我错过了什么?为什么它在登录django管理站点时工作,但在使用django rest framework jwt获取令牌时会出错?
更新
我按照建议制作了另一个身份验证后端并将其添加到DEFAULT_AUTHENTICATION_CLASSES
,但即使这样也无效。
class DrfAuthBackend(BaseAuthentication):
def authenticate(self, username=None, password=None):
try:
user = get_user_model().objects.get(email=username)
if user.check_password(password):
return user, None
except User.DoesNotExist:
if username.isdigit():
try:
user = get_user_model().objects.get(mobile=username)
if user.check_password(password):
return user, None
except User.DoesNotExist:
return None
else:
return None
设定:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAdminUser',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend',
'accounts.email_mobile_auth_backend.DrfAuthBackend',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
更新
将身份验证类中的args
从username
更改为email
似乎无法获取auth_token
,但又无法登录管理网站。
class EmailOrMobileAuthBackend(object):
def authenticate(self, email=None, password=None):
try:
user = get_user_model().objects.get(email=email)
if user.check_password(password):
return user
except User.DoesNotExist:
if email.isdigit():
try:
user = get_user_model().objects.get(mobile=email)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
else:
return None
def get_user(self, user_id):
try:
return get_user_model().objects.get(pk=user_id)
except User.DoesNotExist:
return None
答案 0 :(得分:0)
您应该检查DRF documentation以获取自定义身份验证后端。
我认为您的自定义身份验证后端正在破坏它,您可以通过从DRF设置中删除它来解决它:
$query = "
SELECT *
FROM streamdata_comments t1
JOIN streamdata m
ON";
if ($last_id!==0) {
$query .= " t1.comment_id < $last_id GROUP BY t1.comment_streamitem
AND";
}
$query .= "
m.streamitem_id=t1.comment_streamitem
AND t1.comment_poster=34 AND comment_type_id=1
ORDER BY t1.comment_id DESC LIMIT 2";
$result = mysqli_query($mysqli, $query) or die('Error: ' .
mysqli_error($mysqli));
或者修复你的,这与Django自定义身份验证基本上不一样,因为你应该从REST_FRAMEWORK = {
...
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
扩展并返回一个元组。
authentication.BaseAuthentication
然后在DRF设置中使用它:
from rest_framework import authentication
class DrfAuthBackend(authentication.BaseAuthentication):
def authenticate(self, email=None, password=None):
try:
user = get_user_model().objects.get(email=email)
if user.check_password(password):
return user, None
except User.DoesNotExist:
if email.isdigit():
try:
user = get_user_model().objects.get(mobile=email)
if user.check_password(password):
return user, None
except User.DoesNotExist:
return None
else:
return None
对于Django登录:
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAdminUser',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'accounts.email_mobile_auth_backend.DrfAuthBackend',
'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
),
}
然后进行设置:
class EmailOrMobileAuthBackend(object):
def authenticate(self, username=None, password=None):
try:
user = get_user_model().objects.get(email=username)
if user.check_password(password):
return user
except User.DoesNotExist:
if username.isdigit():
try:
user = get_user_model().objects.get(mobile=username)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
else:
return None
def get_user(self, user_id):
try:
return get_user_model().objects.get(pk=user_id)
except User.DoesNotExist:
return None
答案 1 :(得分:0)
在 settings.py 文件中,添加以下内容:
<块引用>AUTH_USER_MODEL = 'accounts.email_mobile_auth_backend.EmailOrMobileAuthBackend'