2011-11-24 25 views
2

私は、セッション変数のユーザー設定についての情報を保持したいと考えています。ユーザーがログアウトしている間に設定を選択し、後でログインした場合、その設定を再選択する必要なしに、設定を維持する必要があります。ログイン間のセッション変数を維持する

Djangoセッションは、ユーザーセッションを追跡するためにセッションキーをクッキーに保持します。私はそれを理解する方法、ユーザーがログインするこのキーが変更される。

a)は、これはすべてのセッション変数は、ログイン時に削除されるか、過越

Bの任意の並べ替えがある)しない場合には意味していますログイン時の設定を保存できるようにするには、手動でCookieを設定するのが最善の方法ですか? 、しばらくはログアウト

  • 、ログインにクッキー
  • に好みを維持するセッション変数に設定をコピーして、DBへの書き込み(信号を介して?)
  • ログアウト時に、好みでクッキーを更新します。私のようなシナリオを想像します(信号を介して?)

更新

私はユーザーに好みを保存することで、この機能を得ることができましたプロファイルオブジェクト、およびクッキー(これらの設定はどのような場合でも機密性がありません)。ユーザーがログインすると、そのプロファイルの設定が優先されます。ログインしていない場合は、クッキーの嗜好が選択されているあなたは、ログインすると

答えて

2

/(AUTH/のinitの.pyでrequest.session.flush())内の別のユーザーがログインあればDjangoはすべてセッションをフラッシュしますログアウト。

データベースにユーザー設定を格納し、ミドルウェアを追加してそのデータを取得し、要求に格納する方がよいでしょう。それは私が実際にあなたの最初のデザインが意味をなさ考える

+0

これは基本的に私の質問に答える、ありがとう! –

1

ユーザーデータが聞こえます。ログイン/ログアウトの境界にいくつかのセッション変数を保存する場合は、このようなことができます。

from functools import wraps 

class persist_session_vars(object): 
    """ Some views, such as login and logout, will reset all session state. 
    However, we occasionally want to persist some of those session variables. 
    """ 

    session_backup = {} 

    def __init__(self, vars): 
     self.vars = vars 

    def __enter__(self): 
     for var in self.vars: 
      self.session_backup[var] = self.request.session.get(var) 

    def __exit__(self, exc_type, exc_value, traceback): 
     for var in self.vars: 
      self.request.session[var] = self.session_backup.get(var) 

    def __call__(self, test_func, *args, **kwargs): 

     @wraps(test_func) 
     def inner(*args, **kwargs): 
      if not args: 
       raise Exception('Must decorate a view, ie a function taking request as the first parameter') 
      self.request = args[0] 
      with self: 
       return test_func(*args, **kwargs) 

     return inner 

このデコレータは、auth.login/logoutを呼び出すビューに配置してください。それらのビルトインビューに委任している場合、簡単にそれらをラップすることができます。

from django.contrib.auth import views 

@persist_session_vars(['HTTP_REFERER']) 
def login(request, *args, **kwargs): 
    return views.login(request, *args, **kwargs) 
+0

ユーザーがログインするとDBに書き込まれますが、ユーザーがログインしていない場合は、ユーザーが設定を行うことができるようになり、最終的にログインすると、それらの設定がuserprofileモデルを使用しているため、問題はログイン全体でデータを維持しています –

+0

しかし、同じ人か同じブラウザの別のユーザーか分かりません。あなたはこれが同じ人物だと思うのは幸いですか? – second

+0

単純な表示設定はyesですが、設定DBオブジェクトは 'authorized 'としてマークされ、特定の設定だけがクッキーに書き込まれ、すべてがログインされたセッションに書き込まれるようにすることができます。 –

0

UserProfileモデルのようなものに生きるべきのように解消されない

+0

これは素晴らしいスタートですが、スレッドセーフではありません! 'persist_session_vars'は一度インスタンス化されるので、すべてのユーザは同じ' session_backup' dictに書きます(class属性の代わりにオブジェクト変数にしてもここで変更されません) – vdboor

+0

同時に2人のユーザがログインすると、お互いのセッション変数を受け取ります。あなたの例では、あなたの統計はオフになります。しかし、このように個人情報を保持するためには、Webサイトに大きなセキュリティ/情報漏えいが発生します。 – vdboor

0

あなたが(彼らがログインしている必要はありません)、ユーザーのセッションにフォームの値を保持することを可能にするフォームのミックスインを作成することができます。これは、パブリックテーブルビューレポートのフィルタ/ソートオプションなど、フィルタオプションをリフレッシュ間ずっと維持したい場合に便利です。

filter form screenshot

ビュー:

def list_states(request): 
    if request.method == 'GET': 
     form = StateListFilterForm().load_from_session(request.session) 
    elif request.method == 'POST': 
     form = StateListFilterForm(request.POST) 
     form.persist_to_session() 
    return render('forms/state_list.html', RequestContext(request, {'state_form': form}) 

フォーム:ログイン時

class PersistableMixin: 
    def persist_to_session(form, session): 
     for key in form.fields.keys(): 
      val = getattr(form, 'cleaned_data', form.data).get(key, None) 
      if val: # will not store empty str values 
       session[key] = val 
     return True 

    def load_from_session(form, session): 
     for key in form.fields.keys(): 
      saved_val = session.get(key, '') 
      if saved_val: # will not load empty str values 
       form.fields[key].initial = saved_val 
     return form 


class StateListFilterForm(forms.Form, PersistableMixin): 
    states = forms.MultipleChoiceField(required=False, choices=US_STATES) 
3

、Djangoは古いセッションから必ず何も保たれているが行うものではありませんこれは、session.flush()またはsession.cycle_key()を呼び出します。これは、セッション固定の脆弱性からあなたを守るセキュリティ手段です。したがって、このソリューションを適用するときは、どのような変数を見つけるかを知りたいことがあります。

状態を保持したい場合は、ログインが発行された後に復元する必要があります。

Chase Seibertのソリューションはすばらしいスタートでしたが、そのコードのスレッドセーフな問題のために非常に安全ではありませんでした。あなたは使用しても安全である、ここでは改良版を見つけることができます。

class persist_session_vars(object): 
    """ 
    Some views, such as login and logout, will reset all session state. 
    (via a call to ``request.session.cycle_key()`` or ``session.flush()``). 
    That is a security measure to mitigate session fixation vulnerabilities. 

    By applying this decorator, some values are retained. 
    Be very aware what find of variables you want to persist. 
    """ 

    def __init__(self, vars): 
     self.vars = vars 

    def __call__(self, view_func): 

     @wraps(view_func) 
     def inner(request, *args, **kwargs): 
      # Backup first 
      session_backup = {} 
      for var in self.vars: 
       try: 
        session_backup[var] = request.session[var] 
       except KeyError: 
        pass 

      # Call the original view 
      response = view_func(request, *args, **kwargs) 

      # Restore variables in the new session 
      for var, value in session_backup.items(): 
       request.session[var] = value 

      return response 

     return inner 

、今あなたが書くことができます。

from django.contrib.auth import views 

@persist_session_vars(['some_field']) 
def login(request, *args, **kwargs): 
    return views.login(request, *args, **kwargs) 

とクラスベースのビュー(ジャンゴ-allauth)について:

import allauth.account.views as auth_views 
from django.utils.decorators import method_decorator 

@method_decorator(persist_session_vars(['some_field']), name='dispatch') 
class LoginView(auth_views.LoginView): 
    pass 

とそのパターンをURLパターンで使用してください:

import allauth.urls 
from django.conf.urls import include, url 

from . import views 

urlpatterns = [ 
    # Views that overlap the default: 
    url(r'^login/$', views.LoginView.as_view(), name='account_login'), 

    # default allauth urls 
    url(r'', include(allauth.urls)), 
] 
関連する問題