last_login 在 Django Rest Framework 中使用 Tokenauthentication 进行身份验证时,字段未更新
last_login field is not updated when authenticating using Tokenauthentication in Django Rest Framework
我在一个依赖 Django 用户模型和 DjangoRestFramework 下的 TokenAuthentication 的项目中工作
我被要求获取每个用户的上次登录日期时间,我意识到当我调用身份验证 REST 端点时,该字段没有得到更新。
这是众所周知的事实吗?我是否遗漏了一些我必须做的事情,以便在每次调用令牌身份验证时更新该字段?
谢谢
嗯,最后我继承自REST Framework TokenAuthentication,在urls文件中指向它
url(r'^api-token-auth/', back_views.TokenAuthenticationView.as_view()),
View 处理请求并像这样手动调用 update_last_login:
from django.contrib.auth.models import update_last_login
class TokenAuthenticationView(ObtainAuthToken):
"""Implementation of ObtainAuthToken with last_login update"""
def post(self, request):
result = super(TokenAuthenticationView, self).post(request)
try:
request_user, data = requests.get_parameters(request)
user = requests.get_user_by_username(data['username'])
update_last_login(None, user)
except Exception as exc:
return None
return result
@F.D.F。答案很棒。这是另一种方法。
我们发送 user_logged_in
信号,将调用 update_last_login
:
user_logged_in.send(sender=user.__class__, request=request, user=user)
这是一个工作视图(基于使用电子邮件作为 USERNAME_FIELD 的自定义用户模型):
from rest_framework import parsers, renderers
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.auth.signals import user_logged_in
from emailauth.serializers import AuthTokenSerializer, UserSerializer
class ObtainAuthToken(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
user_logged_in.send(sender=user.__class__, request=request, user=user)
return Response({'token': token.key, 'user': UserSerializer(user).data})
obtain_auth_token = ObtainAuthToken.as_view()
您可以在此处找到完整的源代码:Api View with last_login updated
希望这对您有所帮助。
更简洁的方法:
from django.contrib.auth.models import update_last_login
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken
class LoginToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
result = super().post(request, *args, **kwargs)
token = Token.objects.get(key=result.data['token'])
update_last_login(None, token.user)
return result
然后设置 urls.py:
url(r'^api-token-auth/', views.LoginToken.as_view()),
我对 Django==2.0.5
、django-rest-framework-social-oauth2==1.1.0
的回答
from django.contrib.auth import user_logged_in
from oauth2_provider.models import AccessToken
from rest_framework import status
from rest_framework_social_oauth2.views import TokenView
class MyTokenView(TokenView):
def post(self, request, *args, **kwargs):
response = super().post(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
token = AccessToken.objects.get(token=response.data['access_token'])
user = token.user
user_logged_in.send(sender=type(user), request=request, user=user)
return response
urls.py:
from django.urls import path
urlpatterns = [
path('token', MyTokenView.as_view(), name='token'),
]
这是我使用 ViewSet 的解决方案:
views.py:
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework import viewsets
from django.contrib.auth.models import update_last_login
class LoginViewSet(viewsets.ViewSet):
"""Checks email and password and returns an auth token."""
serializer_class = AuthTokenSerializer
def create(self, request):
"""Use the ObtainAuthToken APIView to validate and create a token."""
##update last_login
try:
user = models.User.objects.get(email = request.data['username'])
update_last_login(None, user)
except:
pass
return ObtainAuthToken().post(request)
现在只需将此视图集添加到 urls.py:
router.register('login', views.LoginViewSet, base_name="login")
这是 django 3.0.8 的最新代码。
:)
谢谢 F.D.F.!
from django.contrib.auth.models import update_last_login
from rest_framework.authtoken.views import ObtainAuthToken
from django.contrib.auth import get_user_model
class TokenAuthenticationView(ObtainAuthToken):
"""Implementation of ObtainAuthToken with last_login update"""
def post(self, request):
result = super(TokenAuthenticationView, self).post(request)
currentUserModel = get_user_model()
try:
user = currentUserModel.objects.get(username=request.data['username'])
update_last_login(None, user)
except Exception as exc:
return None
return result
通过信号实现
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth import user_logged_in
from oauth2_provider.models import AccessToken
@receiver(post_save, sender=AccessToken)
def post_save_access_token(instance, created, raw, **kwargs):
if not created or raw:
return
user_logged_in.send(sender=instance.user.__class__, user=instance.user)
对于任何使用 knox 进行用户身份验证的人,都需要编辑 api.py 文件并导入 user_logged_in,如下所示
from django.contrib.auth.signals import user_logged_in
之后,在同一 api.py 文件中的 LoginAPI class 中,在 _, token = AuthToken.objects.create(user) 之后添加以下行,如下所示
user_logged_in.send(sender=user.__class__, request=request, user=user)
如果您使用的是用于 Django 的简单 JWT,您可以按照此 link 非常轻松地完成。你只需要添加
SIMPLE_JWT = {
...,
'UPDATE_LAST_LOGIN': True,
...,
}
我在一个依赖 Django 用户模型和 DjangoRestFramework 下的 TokenAuthentication 的项目中工作
我被要求获取每个用户的上次登录日期时间,我意识到当我调用身份验证 REST 端点时,该字段没有得到更新。
这是众所周知的事实吗?我是否遗漏了一些我必须做的事情,以便在每次调用令牌身份验证时更新该字段?
谢谢
嗯,最后我继承自REST Framework TokenAuthentication,在urls文件中指向它
url(r'^api-token-auth/', back_views.TokenAuthenticationView.as_view()),
View 处理请求并像这样手动调用 update_last_login:
from django.contrib.auth.models import update_last_login
class TokenAuthenticationView(ObtainAuthToken):
"""Implementation of ObtainAuthToken with last_login update"""
def post(self, request):
result = super(TokenAuthenticationView, self).post(request)
try:
request_user, data = requests.get_parameters(request)
user = requests.get_user_by_username(data['username'])
update_last_login(None, user)
except Exception as exc:
return None
return result
@F.D.F。答案很棒。这是另一种方法。
我们发送 user_logged_in
信号,将调用 update_last_login
:
user_logged_in.send(sender=user.__class__, request=request, user=user)
这是一个工作视图(基于使用电子邮件作为 USERNAME_FIELD 的自定义用户模型):
from rest_framework import parsers, renderers
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView
from django.contrib.auth.signals import user_logged_in
from emailauth.serializers import AuthTokenSerializer, UserSerializer
class ObtainAuthToken(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
user_logged_in.send(sender=user.__class__, request=request, user=user)
return Response({'token': token.key, 'user': UserSerializer(user).data})
obtain_auth_token = ObtainAuthToken.as_view()
您可以在此处找到完整的源代码:Api View with last_login updated
希望这对您有所帮助。
更简洁的方法:
from django.contrib.auth.models import update_last_login
from rest_framework.authtoken.models import Token
from rest_framework.authtoken.views import ObtainAuthToken
class LoginToken(ObtainAuthToken):
def post(self, request, *args, **kwargs):
result = super().post(request, *args, **kwargs)
token = Token.objects.get(key=result.data['token'])
update_last_login(None, token.user)
return result
然后设置 urls.py:
url(r'^api-token-auth/', views.LoginToken.as_view()),
我对 Django==2.0.5
、django-rest-framework-social-oauth2==1.1.0
from django.contrib.auth import user_logged_in
from oauth2_provider.models import AccessToken
from rest_framework import status
from rest_framework_social_oauth2.views import TokenView
class MyTokenView(TokenView):
def post(self, request, *args, **kwargs):
response = super().post(request, *args, **kwargs)
if response.status_code == status.HTTP_200_OK:
token = AccessToken.objects.get(token=response.data['access_token'])
user = token.user
user_logged_in.send(sender=type(user), request=request, user=user)
return response
urls.py:
from django.urls import path
urlpatterns = [
path('token', MyTokenView.as_view(), name='token'),
]
这是我使用 ViewSet 的解决方案:
views.py:
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework import viewsets
from django.contrib.auth.models import update_last_login
class LoginViewSet(viewsets.ViewSet):
"""Checks email and password and returns an auth token."""
serializer_class = AuthTokenSerializer
def create(self, request):
"""Use the ObtainAuthToken APIView to validate and create a token."""
##update last_login
try:
user = models.User.objects.get(email = request.data['username'])
update_last_login(None, user)
except:
pass
return ObtainAuthToken().post(request)
现在只需将此视图集添加到 urls.py:
router.register('login', views.LoginViewSet, base_name="login")
这是 django 3.0.8 的最新代码。
:)
谢谢 F.D.F.!
from django.contrib.auth.models import update_last_login
from rest_framework.authtoken.views import ObtainAuthToken
from django.contrib.auth import get_user_model
class TokenAuthenticationView(ObtainAuthToken):
"""Implementation of ObtainAuthToken with last_login update"""
def post(self, request):
result = super(TokenAuthenticationView, self).post(request)
currentUserModel = get_user_model()
try:
user = currentUserModel.objects.get(username=request.data['username'])
update_last_login(None, user)
except Exception as exc:
return None
return result
通过信号实现
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.contrib.auth import user_logged_in
from oauth2_provider.models import AccessToken
@receiver(post_save, sender=AccessToken)
def post_save_access_token(instance, created, raw, **kwargs):
if not created or raw:
return
user_logged_in.send(sender=instance.user.__class__, user=instance.user)
对于任何使用 knox 进行用户身份验证的人,都需要编辑 api.py 文件并导入 user_logged_in,如下所示
from django.contrib.auth.signals import user_logged_in
之后,在同一 api.py 文件中的 LoginAPI class 中,在 _, token = AuthToken.objects.create(user) 之后添加以下行,如下所示
user_logged_in.send(sender=user.__class__, request=request, user=user)
如果您使用的是用于 Django 的简单 JWT,您可以按照此 link 非常轻松地完成。你只需要添加
SIMPLE_JWT = {
...,
'UPDATE_LAST_LOGIN': True,
...,
}