Django会话:修改时更改会话密钥 [英] Django sessions: changing session key when modified

查看:133
本文介绍了Django会话:修改时更改会话密钥的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设置付款网关,并使用会话跨网页请求存储数据。下面的类用于组织和存储信息到会话。

I am setting up a payment gateway and am using sessions to store data across page requests. The class below is used for organizing and storing information to the session.

class Gateway:
  def __init__(self, session_key=None, session_name="FOO"):
    # Store session ID and name
    self.session_key    = session_key
    self.session_name   = session_name

    # Get the session
    session = SessionStore(session_key=self.session_key)

    try :
      data = session[self.session_name]
    except :
      data  = {user_id:None, checked_in:False }

    self.__dict__.update(data)

  def save(self) :
    session = SessionStore(session_key=self.session_key)
    session[self.session_name] = deepcopy(self.__dict__)
      try :
        del session['session_key']
        del session['session_name']
      except :
        pass
    session.save()

查看用户是否登录。如果他/她是,则他/她被重定向。

This view checks to see if the user is logged in. If he/she is, then he/she is redirected. If not, he/she is asked to either login or check in as a guest.

def check_in(request):
  gateway = Gateway(session_key=request.session.session_key)

  if request.user.is_authenticated():
    gateway.user_id = request.user.id
    gateway.checked_in = True
    gateway.save()

    return redirect('next_step')
  else:
    login_form = FormLogin()
    if request.POST:
      data = request.POST.copy()
      if 'login' in data:
        login_form = FormLogin(data)
        if login_form.is_valid():
          user = login(request, login_form)
            if user:
              gateway.user_id = user.id
              gateway.checked_in = True
              gateway.save()
              return redirect('next_step')
        elif 'guest' in data:
          gateway.checked_in = True
          gateway.save()
          return redirect('next_step')
    return render(
      request,
      'shop/login.html',
      {
        'login_form':login_form,
      }
    )

下一个视图检查checked_in变量。这是为了确保用户不会跳过登录/签入过程。 (另一方面,函数login(request,login_form)是在其他上下文中完美工作的函数,如果成功则返回User,否则返回None)

The next view checks the "checked_in" variable. This is to make sure that users are not skipping over the login/checkin process. (As a side note, the function "login(request, login_form)" is a function that is works perfectly in other contexts and returns the User if it was successful and None otherwise)

def next_step(request):
  gateway = Gateway(session_key=request.session.session_key)

  if not gateway.checked_in:#edited 
    messages.info(request, _(u'You must specify login first.'))
    return redirect('check_in')
  else:
    #do the next step

现在问题:

用户被验证,checked_in变量仍然为false,并导致视图循环。每次设置变量并保存时,都会创建一个带有新会话标识的新会话。 django文档对会话修改有一些解释,但我不明白为什么要创建新会话或为什么会话密钥正在更改。

Even when the user is authenticated, the "checked_in" variable is still false and causes the views to loop. A new session with a new session id is created each time that that I set the variable and save. The django docs have some explanation about the modification of sessions, but I cannot understand why new session is being created or why the session key is changing.

编辑:
我正在使用数据库后端。

edit: I am using the database backend.

推荐答案

如果没有访问或修改,Django不会将会话持久化到数据库,所以我相信session_key你正在使用的初始化SessionStore实际上不支持数据库条目。

Django will not persist a session to the database if it has not been accessed or modified, so I believe the session_key you are using to initialise SessionStore is not actually backed by a database entry.

如果是这种情况:当您保存您的SessionStore时,它会自动分配一个新的session_key [1](因为现有的键不存在于DB中,想要避免会话固定[2])并保存到数据库,但客户端将不会分配这个新的session_key,因为您的SessionStore是独立的request.session(它保持不变)。

If this is the case: when you save your SessionStore it will be allocated a new session_key automatically [1] (as the existing key does not exist in the DB and we want to avoid session fixation [2]) and saved to the DB but the client will not be allocated this new session_key because your SessionStore is independent of request.session (which remains unmodified).

[1] https://github.com/django/django/blob/master/django/contrib/sessions/backends/db.py#L22

[2] https:// groups .google.com / forum /?fromgroups#!topic / django-users / 8b_6oTaXv7Q

测试这个假设的简单解决方法是设置请求.session ['kate'] ='bob'在你初始化你的Gateway类之前,因为这应该强制request.session被持久化。您可能想重构您的Gateway类,以便需要访问会话的方法将request.session作为参数。

The simple fix to test this hypothesis out would be to set request.session['kate'] = 'bob' before you initialise your Gateway class as this should force request.session to be persisted. You might like to refactor your Gateway class so that methods that need access to the session take request.session as an argument.

这篇关于Django会话:修改时更改会话密钥的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆