[英]DRF auth_token: "non_field_errors": [ "Unable to log in with provided credentials."
為 Django 編寫的兩個 JWT 包都給我帶來了文檔質量差的問題,所以我嘗試了 DRF-auth_token package。這是我遵循的一個很好的例子, Django Rest Framework Token Authentication 。 理論上你應該能夠 go 到
localhost:8000/api-token-auth/
網址.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."
]
}
設置.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',
)
}
它似乎設置正確。 我數據庫中的每個用戶都有一個令牌。 每個用戶在數據庫中都是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."
]
}
為什么我的用戶無法登錄並獲取他們的令牌? 謝謝
當我嘗試使用此 API 端點時,我收到了相同的錯誤消息:
來自 rest_framework.authtoken.views 的“獲取_auth_token”類,
但驚喜! 問題首先是用戶序列化程序! .
用戶是使用 API endppint 創建的,他們的密碼被保存為純文本!,如下圖所示:用戶數據庫
但是TokenAPI 端點加密了密碼,所以沖突就來了! ,
我已更改User Serializer 類並覆蓋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 Serializer ,數據存儲如下:修改后的用戶數據庫
所以錯誤: “non_field_errors”:[“無法使用提供的憑據登錄。” 停止顯示! ,並且令牌 API 端點“ localhost:8000/api-token-auth/ ”起作用了!
我繼續從drf 令牌身份驗證文檔中執行此操作,並且沒有遇到超級用戶、員工用戶或普通用戶的任何問題。
還可以嘗試按照官方文檔的步驟而不是 SO 答案進行操作,看看是否可以解決問題 - 有可能發生了一些變化。
以下是我采取的一般步驟:
如果您在任何地方都公開了代碼,我很樂意進一步查看並查看我發現的內容。
也許加密是罪魁禍首。 我面臨同樣的問題。 我比較了superuser
和普通用戶(我們稱其為user1
)的 mysql 中存儲的信息。 我發現了一個區別。 superuser
的密碼已加密,但user1
的密碼未加密。 所以我把user1
的密碼改成了superuser
的密碼,然后我把user1
的名字和密碼貼到jwt api,我得到了正確的答案。
現在我找到了一個答案,雖然它可能不是最好的,但它應該有效。 我只是覆蓋了“ModelSerializer”中的“create”方法。 step1:將“create”方法從“ModelSerializer”復制到自己的serializers文件中 step2:將句子“instance = ModelClass._default_manager.create(**validated_data)”改為“instance = ModelClass._default_manager.create_user(**validated_data)” ”。 第3步:它起作用了 ] 4 [ ] 5
對我來說,我創建了密碼為1234
的用戶。
在用戶管理面板中,我看到了以下消息
密碼:無效的密碼格式或未知的散列算法。
使用 django 密碼限制(最少 8 個字符和其他一些字符)更新密碼后,我在 resposne 中獲得了令牌。
密碼不正確
>>> nameko.Platform.Auth({'username': 'user', 'password': 'pass'})
[{'token': 'eefd5c0f747e121b9cb9986290f66b3c1089669d'}, 2
可能有多種原因,但恕我直言,澄清這一點的最簡單方法是激活設置文件中的日志(使用“級別”:“DEBUG”)並通過“api-token-auth”查看生成的 SQL 選擇查詢
例如,我個人在閱讀此請求時跳了出來:
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 驗證方法期望針對username
密鑰的email value
,因為它已經由其他人開發
class User(AbstractUser):
.....
USERNAME_FIELD = 'email'
所以我根據username
提供了它以使其正常工作。
請參閱屏幕截圖以供參考
使用用戶名值
使用電子郵件值
注意:這是因為 Django 根據提到的USERNAME_FIELD
值根據字段查找過濾用戶名值,請參閱下面的代碼參考
user = UserModel._default_manager.get_by_natural_key(username)
我遇到了同樣的問題,我正在使用 Django 4.1。 我是如何解決的:
您的問題的解決方案是備份身份驗證。
要使用 rest_framework.authtoken 登錄,登錄字段是用戶名和密碼。
但是在django jwt把這個字段改成了USERNAME_FIELD。
您需要編寫一個新的 Auth Backend 並將身份驗證 function 參數中的用戶名替換為 USERNAME_FIELD。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.