Я использую Django 1.3, используя промежуточное ПО для сеансов и промежуточное ПО для аутентификации:
# settings.py
SESSION_ENGINE = django.contrib.sessions.backends.db # Persist sessions to DB
SESSION_COOKIE_AGE = 1209600 # Cookies last 2 weeks
Каждый раз, когда пользователь входит в систему из другого места (другого компьютера / браузера), новый Сеанс ( )
создается и сохраняется с уникальным session_id
. Это может привести к созданию нескольких записей в базе данных для одного и того же пользователя. Их логин сохраняется на этом узле до тех пор, пока cookie не будет удален или сеанс не истечет.
Когда пользователь меняет свой пароль, я хочу удалить все неистекшие сеансы для этого пользователя из БД. Таким образом, после смены пароля они будут вынуждены повторно войти в систему. Это сделано в целях безопасности, например, если ваш компьютер украли, или вы случайно оставили себя подключенным к общедоступному терминалу.
Я хочу знать, как лучше всего это оптимизировать. Вот как я это сделал:
# 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()
Очень упрощенное представление:
# 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 .objects.filter (expire_date__gte = datetime.datetime.now ())
, декодируйте их все, а затем проверьте, соответствует ли он пользователю или нет. Это будет очень дорого обходиться базе данных, если в ней хранится, скажем, более 100 000 сеансов.
Есть ли более удобный для базы данных способ сделать это? Есть ли параметр Sessions / Auth Middleware, который позволит вам сохранить имя пользователя в виде столбца в таблице Sessions, чтобы я мог запускать SQL для этого, или мне придется изменить сеансы для этого? По умолчанию в нем есть только столбцы session_key
, session_data
и expire_date
.
Спасибо за любую информацию или помощь, которую вы можете предложить. :)