[英]Django Rest Framework Custom JWT authentication
I created a Django app in which I want to be able to authenticate users by checking not only the username and password, but also a specific field in a related model.我创建了一个 Django 应用程序,我希望能够在其中通过不仅检查用户名和密码,而且检查相关模型中的特定字段来对用户进行身份验证。 The custom request body I want to POST
to the endpoint is:自定义请求主体我想POST
到端点是:
payload = { 'username': user, 'password': password, 'app_id': uuid4}
I am using djangorestframework-simplejwt
module to get the access token.我正在使用djangorestframework-simplejwt
模块来获取访问令牌。
models.py模型.py
class Application(models.Model):
app_name = models.CharField(max_length=300)
app_id = models.UUIDField(default=uuid.uuid4, editable=False)
def __str__(self):
return self.app_name
class ProfileApp(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
app = models.ForeignKey(Application, on_delete=models.CASCADE)
expires_on = models.DateTimeField(default=datetime.now() + timedelta(days=15))
def __str__(self):
return self.app.app_name + " | " + self.user.username
Is it possible to override the TokenObtainPairView
from rest_framework_simplejwt
to only authenticate an user if the expires_on
date is still not expired?是否有可能重写TokenObtainPairView
从rest_framework_simplejwt
如果只认证的用户expires_on
日期还没有结束? Or is there an architecture problem by doing it like this?或者这样做是否存在架构问题?
You can do this by creating a custom serializer that inherits from TokenObtainPairSerializer
, and extending the validate
method to check for custom field values.您可以通过创建一个继承自TokenObtainPairSerializer
的自定义序列化程序并扩展validate
方法来检查自定义字段值来实现此目的。 There is no architecture problem if you are careful to not override necessary functionality of the parent class.如果您小心地不覆盖父类的必要功能,则不存在体系结构问题。
Here is an example:下面是一个例子:
import datetime as dt
import json
from rest_framework import exceptions
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
try:
request = self.context["request"]
except KeyError:
pass
else:
request_data = json.loads(request.body)
username = request_data.get("username")
app_id = request_data.get("app_id")
profile_has_expired = False
try:
profile = ProfileApp.objects.get(user__username=username, app__app_id=app_id)
except ProfileApp.DoesNotExist:
profile_has_expired = True
else:
profile_has_expired = dt.date.today() > profile.expires_on
finally:
if profile_has_expired:
error_message = "This profile has expired"
error_name = "expired_profile"
raise exceptions.AuthenticationFailed(error_message, error_name)
finally:
return super().validate(attrs)
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
Then use MyTokenObtainPairView
in place of TokenObtainPairView
in your urls file.然后在您的 urls 文件中使用MyTokenObtainPairView
代替TokenObtainPairView
。
Also since User
and ProfileApp
share a one-to-one field, it looks like you can get away with not using the "app_id
" key/field at all.此外,由于User
和ProfileApp
共享一个一对一的字段,看起来您可以完全不使用"app_id
”键/字段。
Original source file: https://github.com/davesque/django-rest-framework-simplejwt/blob/04376b0305e8e2fda257b08e507ccf511359d04a/rest_framework_simplejwt/serializers.py原始源文件: https : //github.com/davesque/django-rest-framework-simplejwt/blob/04376b0305e8e2fda257b08e507ccf511359d04a/rest_framework_simplejwt/serializers.py
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.