cod*_*321 5 python django django-rest-framework django-rest-auth django-1.10
为 Django 编写的两个 JWT 包都给我带来了文档不佳的问题,所以我尝试了 DRF-auth_token 包。这是我遵循的一个很好的例子,Django Rest Framework Token Authentication。理论上你应该能够去
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'),
]
Run Code Online (Sandbox Code Playgroud)
为用户获取令牌不起作用,所以我自己重写了它以使其工作:
@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)
Run Code Online (Sandbox Code Playgroud)
我的版本有效:
http://localhost:8000/api/login/customer-login/
{"username": "thisguy@example.com", "password": "wombat"}
-->
{
"token": "292192b101153b7ced74dd52deb6b3df22ef2c74"
}
Run Code Online (Sandbox Code Playgroud)
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."
]
}
Run Code Online (Sandbox Code Playgroud)
设置.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',
)
}
Run Code Online (Sandbox Code Playgroud)
似乎设置正确。我数据库中的每个用户都有一个令牌。每个用户is_authenticated和is_active在DB。超级用户可以获得他们的代币:
localhost:8000/api-token-auth/
{"username": "mysuperuser", "password": "superuserpassword"}
-->
{
"token": "9297ff1f44dbc6caea67bea534f6f7590d2161b0"
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,只有超级用户才能获得令牌:
localhost:8000/api-token-auth/
{"username": "regularguy", "password": "password"}
-->
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
Run Code Online (Sandbox Code Playgroud)
为什么我的用户无法登录并获取他们的令牌?谢谢
小智 20
当我尝试使用此 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
Run Code Online (Sandbox Code Playgroud)现在我已经编辑了我的 User Serializer ,数据存储如下: 修改后的用户数据库
所以错误:“non_field_errors”:[“无法使用提供的凭据登录。” 停止显示!,并且令牌 API 端点“ localhost:8000/api-token-auth/ ”起作用了!
我继续从drf 令牌身份验证文档中执行此操作,并且没有遇到超级用户、员工用户或普通用户的任何问题。
还可以尝试按照官方文档的步骤而不是 SO 答案进行操作,看看是否可以解决问题 - 有可能发生了一些变化。
以下是我采取的一般步骤:
如果您在任何地方都公开了代码,我很乐意进一步查看并查看我发现的内容。
也许加密是罪魁祸首。我面临同样的问题。我比较了存储在mysql中的信息superuser和一个普通用户(姑且称之为user1)。我发现了一个区别。的密码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