簡體   English   中英

DRF auth_token:“non_field_errors”:[“無法使用提供的憑據登錄。”

[英]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_authenticatedis_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 答案進行操作,看看是否可以解決問題 - 有可能發生了一些變化。

以下是我采取的一般步驟:

  • 安裝 django,drf
  • 將 'rest_framework' 和 'rest_framework.authtoken' 放入 INSTALLED_APPS
  • 在我的 rest_framework 設置中添加“TokenAuthentication”
  • 運行遷移
  • 為用戶創建令牌(我只是在 urls.py 中做到了這一點)
  • 為令牌創建網址
  • POST http://localhost:8000/token/ {"username": "...", "password": "..."}

如果您在任何地方都公開了代碼,我很樂意進一步查看並查看我發現的內容。

也許加密是罪魁禍首。 我面臨同樣的問題。 我比較了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

  1. 檢查用戶名和密碼
  2. 表 users.is_active = 1 中的字段

對我來說,我創建了密碼為1234的用戶。

在用戶管理面板中,我看到了以下消息

密碼:無效的密碼格式或未知的散列算法。

使用 django 密碼限制(最少 8 個字符和其他一些字符)更新密碼后,我在 resposne 中獲得了令牌。

我希望這對使用TokenAuthentication (不是 JWT)、 django-allauthdj-rest-auth並遇到相同錯誤的人TokenAuthentication幫助。

這個來自另一個類似問題的答案對我有用。

我只需要在settings.py上添加這些身份驗證后端:

AUTHENTICATION_BACKENDS = (
   "django.contrib.auth.backends.ModelBackend",
   "allauth.account.auth_backends.AuthenticationBackend"
)

密碼不正確

>>> 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 不再是用戶名,而是電子郵件。

就我而言,我使用usernamepassword進行身份驗證。 但是由於項目中的以下自定義代碼,django 驗證方法期望針對username密鑰的email value ,因為它已經由其他人開發

class User(AbstractUser):
    .....
    USERNAME_FIELD = 'email'

所以我根據username提供了它以使其正常工作。

請參閱屏幕截圖以供參考

使用用戶名值

在此處輸入圖片說明

使用電子郵件值

在此處輸入圖片說明

注意:這是因為 Django 根據提到的USERNAME_FIELD值根據字段查找過濾用戶名值,請參閱下面的代碼參考

https://github.com/django/django/blob/61d5e57353bb811df7b5457a1856baee31299429/django/contrib/auth/backends.py#L42

user = UserModel._default_manager.get_by_natural_key(username)

我遇到了同樣的問題,我正在使用 Django 4.1。 我是如何解決的:

  1. 如果您要創建超級用戶,請提供強密碼。 有時它不會提供發生在我身上的弱密碼錯誤,然后不會生成令牌。
  2. 如果您通過代碼創建用戶,請確保將密碼存儲為 hash。
  3. 在 setting.py installed_apps=[ 'rest_framework.authtoken',] 中添加以下 class

    現在,試一試吧!

您的問題的解決方案是備份身份驗證。

要使用 rest_framework.authtoken 登錄,登錄字段是用戶名和密碼。

但是在django jwt把這個字段改成了USERNAME_FIELD。

您需要編寫一個新的 Auth Backend 並將身份驗證 function 參數中的用戶名替換為 USERNAME_FIELD。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM