Sessions Middleware と Auth Middleware を使用して、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()
が作成され、一意のsession_id
. これにより、同じユーザーに対して複数のデータベース エントリが作成される可能性があります。ログインは、Cookie が削除されるか、セッションが期限切れになるまで、そのノードに保持されます。
ユーザーがパスワードを変更すると、そのユーザーの有効期限が切れていないすべてのセッションを DB から削除したいと考えています。そうすれば、パスワードの変更後、再ログインが強制されます。これは、コンピューターが盗難にあった場合や、誤って公衆端末にログインしたままにした場合などのセキュリティ上の目的のためです。
これを最適化する最良の方法を知りたいです。これが私がやった方法です:
# 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
、期限切れになっていないすべてのセッションを DB から取り出し、Session.objects.filter(expire_date__gte=datetime.datetime.now())
すべてをデコードしてから、ユーザーと一致するかどうかを確認する必要があります。データベースに 100,000 以上のセッションが保存されている場合、これはデータベースにとって非常にコストがかかります。
これを行うためのよりデータベースに適した方法はありますか? ユーザー名をSessionsテーブルの列として保存できるようにするSessions / Auth Middleware設定はありますか?それに対してSQLを実行できますか?それを行うにはSessionsを変更する必要がありますか? すぐに使用できるのはsession_key
、、、session_data
およびexpire_date
列のみです。
あなたが提供できる洞察や助けに感謝します。:)