我应该如何使用 graphql JWT 跟踪用户的最后活动时间?
How should I track the last active time of an user using graphql JWT?
我正在记录用户登录信息,包括 OS、浏览器、IP 和设备。我想在 30 天没有 activity 期后将其删除。问题是我的用户使用智能手机,他们登录后几乎 re-login。我像这样覆盖 graphql_jwt.JSONWebTokenMutation:
class ObtainJSONWebToken(graphql_jwt.JSONWebTokenMutation):
class Arguments:
push_token = graphene.String()
user = graphene.Field(UserType)
@classmethod
def resolve(cls, root, info, push_token=None, **kwargs):
ip, is_routable = get_client_ip(info.context, ['HTTP_X_FORWARDED_FOR', 'X_FORWARDED_FOR', 'REMOTE_ADDR'])
ua_string = info.context.META['HTTP_USER_AGENT']
user_agent = parse(ua_string)
if user_agent.is_pc is True:
device = 'Desktop'
else:
device = user_agent.device.family
OS = user_agent.os.family + ' ' + user_agent.os.version_string
browser = user_agent.browser.family + ' ' + user_agent.browser.version_string
try:
login_info = models.UserLoginInfo.objects.get(user=info.context.user, ip=ip, device=device,
push_token=push_token, OS=OS, browser=browser)
login_info.save()
except models.UserLoginInfo.DoesNotExist:
if push_token is not None:
try:
duplicated_push_token_info = models.UserLoginInfo.objects.get(push_token=push_token)
duplicated_push_token_info.push_token = None
duplicated_push_token_info.save()
except models.UserLoginInfo.DoesNotExist:
pass
print(ip, device, OS, browser)
login_info = models.UserLoginInfo(user=info.context.user, ip=ip, device=device,
push_token=push_token, OS=OS, browser=browser)
login_info.save()
info.context.user.last_login = login_info.last_login
info.context.user.save()
return cls(user=info.context.user)
但是我很快就发现了一个问题。如上所述,上次登录时间仅在用户登录时更新。所以我无法删除过去 30 天的 UserLoginInfo。那么我应该如何使用 graphql jwt 更新用户的上次活动时间?
我在授权 header 中为每个需要身份验证的请求添加了一个 JWT 令牌。它由 graphql_jwt 自动处理。我所做的就是使用 @login_required 装饰器。但我想覆盖@login_required.
的解析器
更新用户上次活动时间的最佳位置是 中间件,因为每个请求都经过它,因此您可以确信任何activity 已跟踪。
例如覆盖 login_required
装饰器只会影响使用它的端点,如果使用多个这样的装饰端点来解析 graphql 查询,那么每个装饰器都会访问数据库以更新上次活动时间,因此会导致不必要的服务器负载。
Django 最后一个活动中间件示例:
class UpdateLastActivityMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.user.is_authenticated:
User.objects.filter(pk=request.user.id) \
.update(last_activity=timezone.now())
response = self.get_response(request)
return response
在认证中间件之后包含它:
MIDDLEWARE = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'your_package.middleware.UpdateLastActivityMiddleware',
...
]
注意:它不是石墨烯中间件,因为它在每个字段分辨率上被调用,但最后一个activity应该是每个请求更新一次(这正是 django 中间件提供的)。
我正在记录用户登录信息,包括 OS、浏览器、IP 和设备。我想在 30 天没有 activity 期后将其删除。问题是我的用户使用智能手机,他们登录后几乎 re-login。我像这样覆盖 graphql_jwt.JSONWebTokenMutation:
class ObtainJSONWebToken(graphql_jwt.JSONWebTokenMutation):
class Arguments:
push_token = graphene.String()
user = graphene.Field(UserType)
@classmethod
def resolve(cls, root, info, push_token=None, **kwargs):
ip, is_routable = get_client_ip(info.context, ['HTTP_X_FORWARDED_FOR', 'X_FORWARDED_FOR', 'REMOTE_ADDR'])
ua_string = info.context.META['HTTP_USER_AGENT']
user_agent = parse(ua_string)
if user_agent.is_pc is True:
device = 'Desktop'
else:
device = user_agent.device.family
OS = user_agent.os.family + ' ' + user_agent.os.version_string
browser = user_agent.browser.family + ' ' + user_agent.browser.version_string
try:
login_info = models.UserLoginInfo.objects.get(user=info.context.user, ip=ip, device=device,
push_token=push_token, OS=OS, browser=browser)
login_info.save()
except models.UserLoginInfo.DoesNotExist:
if push_token is not None:
try:
duplicated_push_token_info = models.UserLoginInfo.objects.get(push_token=push_token)
duplicated_push_token_info.push_token = None
duplicated_push_token_info.save()
except models.UserLoginInfo.DoesNotExist:
pass
print(ip, device, OS, browser)
login_info = models.UserLoginInfo(user=info.context.user, ip=ip, device=device,
push_token=push_token, OS=OS, browser=browser)
login_info.save()
info.context.user.last_login = login_info.last_login
info.context.user.save()
return cls(user=info.context.user)
但是我很快就发现了一个问题。如上所述,上次登录时间仅在用户登录时更新。所以我无法删除过去 30 天的 UserLoginInfo。那么我应该如何使用 graphql jwt 更新用户的上次活动时间?
我在授权 header 中为每个需要身份验证的请求添加了一个 JWT 令牌。它由 graphql_jwt 自动处理。我所做的就是使用 @login_required 装饰器。但我想覆盖@login_required.
的解析器更新用户上次活动时间的最佳位置是 中间件,因为每个请求都经过它,因此您可以确信任何activity 已跟踪。
例如覆盖 login_required
装饰器只会影响使用它的端点,如果使用多个这样的装饰端点来解析 graphql 查询,那么每个装饰器都会访问数据库以更新上次活动时间,因此会导致不必要的服务器负载。
Django 最后一个活动中间件示例:
class UpdateLastActivityMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.user.is_authenticated:
User.objects.filter(pk=request.user.id) \
.update(last_activity=timezone.now())
response = self.get_response(request)
return response
在认证中间件之后包含它:
MIDDLEWARE = [
...
'django.contrib.auth.middleware.AuthenticationMiddleware',
'your_package.middleware.UpdateLastActivityMiddleware',
...
]
注意:它不是石墨烯中间件,因为它在每个字段分辨率上被调用,但最后一个activity应该是每个请求更新一次(这正是 django 中间件提供的)。