gpt4 book ai didi

python - 在 Django 中删除特定用户的所有 session 的最优化方法?

转载 作者:IT老高 更新时间:2023-10-28 21:11:53 24 4
gpt4 key购买 nike

我正在运行 Django 1.3,使用 Sessions Middleware 和 Auth Middleware:

# settings.py

SESSION_ENGINE = django.contrib.sessions.backends.db # Persist sessions to DB
SESSION_COOKIE_AGE = 1209600 # Cookies last 2 weeks

每次用户从不同的位置(不同的计算机/浏览器)登录时,都会创建一个新的 Session(),并使用唯一的 session_id 进行保存。这可能导致同一用户有多个数据库条目。他们的登录在该节点上持续存在,直到 cookie 被删除或 session 过期。

当用户更改密码时,我想从数据库中删除该用户的所有未过期 session 。这样,在更改密码后,他们将被迫重新登录。这是出于安全目的,例如如果您的计算机被盗,或者您不小心在公共(public)终端上保持登录状态。

我想知道优化它的最佳方法。这是我的做法:

# sessions_helpers.py

from django.contrib.sessions.models import Session
import datetime

def all_unexpired_sessions_for_user(user):
user_sessions = []
all_sessions = Session.objects.filter(expire_date__gte=datetime.datetime.now())
for session in all_sessions:
session_data = session.get_decoded()
if user.pk == session_data.get('_auth_user_id'):
user_sessions.append(session)
return user_sessions

def delete_all_unexpired_sessions_for_user(user, session_to_omit=None):
for session in all_unexpired_sessions_for_user(user):
if session is not session_to_omit:
session.delete()

一个非常简化的 View :

# views.py

from django.http import HttpResponse
from django.shortcuts import render_to_response
from myapp.forms import ChangePasswordForm
from sessions_helpers import delete_all_unexpired_sessions_for_user

@never_cache
@login_required
def change_password(request):
user = request.user

if request.method == 'POST':
form = ChangePasswordForm(data=request)

if form.is_valid():
user.set_password(form.get('password'))
user.save()
request.session.cycle_key() # Flushes and replaces old key. Prevents replay attacks.
delete_all_unexpired_sessions_for_user(user=user, session_to_omit=request.session)
return HttpResponse('Success!')

else:
form = ChangePasswordForm()

return render_to_response('change_password.html', {'form':form}, context_instance=RequestContext(request))

正如您在 sessions_helpers.py 中看到的,我必须将每个未过期的 session 从数据库中拉出,Session.objects.filter(expire_date__gte=datetime.datetime.now()) ,将它们全部解码,然后检查它是否匹配用户。如果其中存储了 100,000 多个 session ,这对数据库来说将是非常昂贵的。

有没有一种对数据库更友好的方法来做到这一点?是否有 Sessions/Auth Middleware 设置可以让您将用户名存储为 Sessions 表中的列,以便我可以针对它运行 SQL,还是必须修改 Sessions 才能做到这一点?开箱即用它只有 session_keysession_dataexpire_date 列。

感谢您提供的任何见解或帮助。 :)

最佳答案

如果您从 all_unexpired_sessions_for_user 函数返回一个 QuerySet,您可以将数据库命中限制为两个:

def all_unexpired_sessions_for_user(user):
user_sessions = []
all_sessions = Session.objects.filter(expire_date__gte=datetime.datetime.now())
for session in all_sessions:
session_data = session.get_decoded()
if user.pk == session_data.get('_auth_user_id'):
user_sessions.append(session.pk)
return Session.objects.filter(pk__in=user_sessions)

def delete_all_unexpired_sessions_for_user(user, session_to_omit=None):
session_list = all_unexpired_sessions_for_user(user)
if session_to_omit is not None:
session_list.exclude(session_key=session_to_omit.session_key)
session_list.delete()

这为您提供了对数据库的总共两次命中。一次循环所有 Session 对象,一次删除所有 session 。不幸的是,我不知道有更直接的方法来过滤 session 本身。

关于python - 在 Django 中删除特定用户的所有 session 的最优化方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6656708/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com