DRF auth_token: "non_field_errors": [ "Unable to log in with provided credentials."
DRF auth_token: "non_field_errors": [ "Unable to log in with provided credentials."
为 Django 编写的两个 JWT 包都给我带来了文档质量差的问题,所以我尝试 DRF-auth_token 包。这是我遵循的一个很好的例子,Django Rest Framework Token Authentication。理论上你应该能够去
localhost:8000/api-token-auth/
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
from django.contrib.auth.models import User
from rest_framework.authtoken import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls', namespace='api')),
url(r'^orders/', include('orders.urls', namespace='orders')),
url(r'^api-token-auth/', views.obtain_auth_token, name='auth-token'),
]
为用户获取令牌不起作用,所以我自己重写了它以使其起作用:
@api_view(['POST'])
def customer_login(request):
"""
Try to login a customer (food orderer)
"""
data = request.data
try:
username = data['username']
password = data['password']
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
try:
user = User.objects.get(username=username, password=password)
except:
return Response(status=status.HTTP_401_UNAUTHORIZED)
try:
user_token = user.auth_token.key
except:
user_token = Token.objects.create(user=user)
data = {'token': user_token}
return Response(data=data, status=status.HTTP_200_OK)
我的版本有效:
http://localhost:8000/api/login/customer-login/
{"username": "thisguy@example.com", "password": "wombat"}
-->
{
"token": "292192b101153b7ced74dd52deb6b3df22ef2c74"
}
DRF auth_token 不工作:
http://localhost:8000/api-token-auth/
{"username": "thisguy@example.com", "password": "wombat"}
-->
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# third party:
'django_extensions',
'rest_framework',
'rest_framework.authtoken',
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
似乎设置正确。我数据库中的每个用户都有一个令牌。每个用户在 DB 中是 is_authenticated
和 is_active
。超级用户可以获得他们的令牌:
localhost:8000/api-token-auth/
{"username": "mysuperuser", "password": "superuserpassword"}
-->
{
"token": "9297ff1f44dbc6caea67bea534f6f7590d2161b0"
}
由于某些原因,只有超级用户才能获得令牌:
localhost:8000/api-token-auth/
{"username": "regularguy", "password": "password"}
-->
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
为什么我的用户无法登录并获取他们的令牌?谢谢
我从 drf token auth docs 开始执行此操作,并且 运行 没有遇到任何与超级用户、员工用户或普通用户有关的问题。
也尝试按照官方文档的步骤而不是那个 SO 答案,看看是否能解决问题 - 可能发生了一些变化。
以下是我采取的一般步骤:
- 安装django、drf
- 将'rest_framework'和'rest_framework.authtoken'放入INSTALLED_APPS
- 在我的 rest_framework 设置中添加 'TokenAuthentication'
- 运行 迁移
- 为用户创建令牌(我刚刚在 urls.py 中做了这个)
- 为令牌
创建url
- POST http://localhost:8000/token/ {"username": "...", "password": "..."}
如果您在任何地方都有代码 public,我很乐意进一步查看,看看我找到了什么。
- 检查用户名和密码
- table 中的字段 users.is_active = 1
也许加密是罪魁祸首。我面临着同样的问题。我比较了superuser
的mysql和一个普通用户(姑且称之为user1
)中存储的信息。我发现了不同之处。 superuser
的密码已加密,但user1
的密码未加密。所以我把user1
的密码改成了superuser
的密码,然后我posted the name and password of user1
to the jwt api and I got the right answer.
现在我找到了一个答案,虽然它可能不是最好的,但它应该有用。
我刚刚覆盖了 "ModelSerializer" 中的 "create" 方法。
第一步:将 "create" 方法从 "ModelSerializer" 复制到您自己的序列化程序文件
step2:将句子"instance = ModelClass._default_manager.create(**validated_data)"改成"instance = ModelClass._default_manager.create_user(**validated_data)".
第三步:成功了]4
[]5
当我尝试使用此 API 端点时收到相同的错误消息:
“obtain_auth_token”来自 rest_framework.authtoken.views 的 class,
但是 惊喜!问题是 User serializer 在
第一名 ! .
用户 是使用 API endppint 创建的,他们的密码被保存为纯文本!,如以下屏幕截图所示:
User Database
但是 令牌 API 端点加密了密码 ,所以 冲突 就从那里来了! ,
我已经更改了 User Serializer class 并覆盖 create 函数以使用 set_password 散列密码的函数:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'password']
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
user = User(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
现在我已经编辑了我的用户序列化程序,数据存储如下:
User database after modification
所以错误:“non_field_errors”:[“无法使用提供的凭据登录。” 停止显示! ,并且令牌 API 端点“localhost:8000/api-token-auth/”有效!
对我来说,我创建了密码为 1234
的用户。
在用户管理面板中我看到了下面的消息
Password: Invalid password format or unknown hashing algorithm.
使用 django 密码限制(最少 8 个字符和其他一些字符)更新密码后,我在响应中获得了令牌。
密码不正确
>>> nameko.Platform.Auth({'username': 'user', 'password': 'pass'})
[{'token': 'eefd5c0f747e121b9cb9986290f66b3c1089669d'}, 2
可能有多种原因,但恕我直言,澄清这一点的最简单方法是激活设置文件中的日志(使用“level”:“DEBUG”)并查看生成的 SQL 选择通过“api-token-auth”查询
例如,我个人在阅读此请求时跳了出来:
SELECT
profileapp_customuser.id, profileapp_customuser.password,
profileapp_customuser.last_login, profileapp_customuser.is_superuser,
[...]
profileapp_customuser.email FROM profileapp_customuser
WHERE
**profileapp_customuser.email = 'username_test3**' LIMIT 21;
事实上,我的自定义模型无法运行,因为我的用户唯一 ID 不再是用户名而是电子邮件。
在我的案例中,我使用 username
和 password
进行身份验证。但是 django authentite 方法期望 email value
反对 username
关键,因为项目中的以下自定义代码已经存在,由其他人开发
class User(AbstractUser):
.....
USERNAME_FIELD = 'email'
所以我提供了反对 username
的功能。
参考截图
Using Username value
Using Email value
注意:这是因为 Django 根据提到的字段查找过滤用户名值 USERNAME_FIELD
值请参阅下面的代码参考
user = UserModel._default_manager.get_by_natural_key(username)
我希望这对那些使用 TokenAuthentication
(不是 JWT)、django-allauth
和 dj-rest-auth
并遇到相同错误的人有所帮助。
来自另一个类似问题的 对我有用。
我只需要在 settings.py
上添加这些身份验证后端:
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend"
)
为 Django 编写的两个 JWT 包都给我带来了文档质量差的问题,所以我尝试 DRF-auth_token 包。这是我遵循的一个很好的例子,Django Rest Framework Token Authentication。理论上你应该能够去
localhost:8000/api-token-auth/
urls.py:
from django.conf.urls import url, include
from django.contrib import admin
from django.contrib.auth.models import User
from rest_framework.authtoken import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls', namespace='api')),
url(r'^orders/', include('orders.urls', namespace='orders')),
url(r'^api-token-auth/', views.obtain_auth_token, name='auth-token'),
]
为用户获取令牌不起作用,所以我自己重写了它以使其起作用:
@api_view(['POST'])
def customer_login(request):
"""
Try to login a customer (food orderer)
"""
data = request.data
try:
username = data['username']
password = data['password']
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
try:
user = User.objects.get(username=username, password=password)
except:
return Response(status=status.HTTP_401_UNAUTHORIZED)
try:
user_token = user.auth_token.key
except:
user_token = Token.objects.create(user=user)
data = {'token': user_token}
return Response(data=data, status=status.HTTP_200_OK)
我的版本有效:
http://localhost:8000/api/login/customer-login/
{"username": "thisguy@example.com", "password": "wombat"}
-->
{
"token": "292192b101153b7ced74dd52deb6b3df22ef2c74"
}
DRF auth_token 不工作:
http://localhost:8000/api-token-auth/
{"username": "thisguy@example.com", "password": "wombat"}
-->
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# third party:
'django_extensions',
'rest_framework',
'rest_framework.authtoken',
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
似乎设置正确。我数据库中的每个用户都有一个令牌。每个用户在 DB 中是 is_authenticated
和 is_active
。超级用户可以获得他们的令牌:
localhost:8000/api-token-auth/
{"username": "mysuperuser", "password": "superuserpassword"}
-->
{
"token": "9297ff1f44dbc6caea67bea534f6f7590d2161b0"
}
由于某些原因,只有超级用户才能获得令牌:
localhost:8000/api-token-auth/
{"username": "regularguy", "password": "password"}
-->
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
为什么我的用户无法登录并获取他们的令牌?谢谢
我从 drf token auth docs 开始执行此操作,并且 运行 没有遇到任何与超级用户、员工用户或普通用户有关的问题。
也尝试按照官方文档的步骤而不是那个 SO 答案,看看是否能解决问题 - 可能发生了一些变化。
以下是我采取的一般步骤:
- 安装django、drf
- 将'rest_framework'和'rest_framework.authtoken'放入INSTALLED_APPS
- 在我的 rest_framework 设置中添加 'TokenAuthentication'
- 运行 迁移
- 为用户创建令牌(我刚刚在 urls.py 中做了这个)
- 为令牌 创建url
- POST http://localhost:8000/token/ {"username": "...", "password": "..."}
如果您在任何地方都有代码 public,我很乐意进一步查看,看看我找到了什么。
- 检查用户名和密码
- table 中的字段 users.is_active = 1
也许加密是罪魁祸首。我面临着同样的问题。我比较了superuser
的mysql和一个普通用户(姑且称之为user1
)中存储的信息。我发现了不同之处。 superuser
的密码已加密,但user1
的密码未加密。所以我把user1
的密码改成了superuser
的密码,然后我posted the name and password of user1
to the jwt api and I got the right answer.
现在我找到了一个答案,虽然它可能不是最好的,但它应该有用。
我刚刚覆盖了 "ModelSerializer" 中的 "create" 方法。
第一步:将 "create" 方法从 "ModelSerializer" 复制到您自己的序列化程序文件
step2:将句子"instance = ModelClass._default_manager.create(**validated_data)"改成"instance = ModelClass._default_manager.create_user(**validated_data)".
当我尝试使用此 API 端点时收到相同的错误消息:
“obtain_auth_token”来自 rest_framework.authtoken.views 的 class,
但是 惊喜!问题是 User serializer 在 第一名 ! .用户 是使用 API endppint 创建的,他们的密码被保存为纯文本!,如以下屏幕截图所示: User Database
但是 令牌 API 端点加密了密码 ,所以 冲突 就从那里来了! ,我已经更改了 User Serializer class 并覆盖 create 函数以使用 set_password 散列密码的函数:
class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['email', 'username', 'password'] extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): user = User( email=validated_data['email'], username=validated_data['username'] ) user.set_password(validated_data['password']) user.save() return user
现在我已经编辑了我的用户序列化程序,数据存储如下: User database after modification
所以错误:“non_field_errors”:[“无法使用提供的凭据登录。” 停止显示! ,并且令牌 API 端点“localhost:8000/api-token-auth/”有效!
对我来说,我创建了密码为 1234
的用户。
在用户管理面板中我看到了下面的消息
Password: Invalid password format or unknown hashing algorithm.
使用 django 密码限制(最少 8 个字符和其他一些字符)更新密码后,我在响应中获得了令牌。
密码不正确
>>> nameko.Platform.Auth({'username': 'user', 'password': 'pass'})
[{'token': 'eefd5c0f747e121b9cb9986290f66b3c1089669d'}, 2
可能有多种原因,但恕我直言,澄清这一点的最简单方法是激活设置文件中的日志(使用“level”:“DEBUG”)并查看生成的 SQL 选择通过“api-token-auth”查询
例如,我个人在阅读此请求时跳了出来:
SELECT
profileapp_customuser.id, profileapp_customuser.password,
profileapp_customuser.last_login, profileapp_customuser.is_superuser,
[...]
profileapp_customuser.email FROM profileapp_customuser
WHERE
**profileapp_customuser.email = 'username_test3**' LIMIT 21;
事实上,我的自定义模型无法运行,因为我的用户唯一 ID 不再是用户名而是电子邮件。
在我的案例中,我使用 username
和 password
进行身份验证。但是 django authentite 方法期望 email value
反对 username
关键,因为项目中的以下自定义代码已经存在,由其他人开发
class User(AbstractUser):
.....
USERNAME_FIELD = 'email'
所以我提供了反对 username
的功能。
参考截图
Using Username value
Using Email value
注意:这是因为 Django 根据提到的字段查找过滤用户名值 USERNAME_FIELD
值请参阅下面的代码参考
user = UserModel._default_manager.get_by_natural_key(username)
我希望这对那些使用 TokenAuthentication
(不是 JWT)、django-allauth
和 dj-rest-auth
并遇到相同错误的人有所帮助。
我只需要在 settings.py
上添加这些身份验证后端:
AUTHENTICATION_BACKENDS = (
"django.contrib.auth.backends.ModelBackend",
"allauth.account.auth_backends.AuthenticationBackend"
)