Reputation: 31
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,
}
)
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
Now for the problem:
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.
Upvotes: 3
Views: 5892
Reputation: 600
Check your SESSION_COOKIE_SECURE
value and make sure you are using HTTPS when True
..
https://github.com/lepture/flask-wtf/issues/76
Upvotes: -1
Reputation: 2688
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.
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
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.
Upvotes: 1
Reputation: 10919
I have duplicated this bug/issue:
URL RULE
url(r'^test/', 'shop.views.catalog.test', name="test")
VIEW FUNCTION
def test(request) :
key1 = request.session.session_key
request.session['test'] = 'test'
key2 = request.session.session_key
raise Exception("%s : %s === %s" % (key1, key2, request.session['test']))
so until the first time my session is modified, I have a different session key... unexpected behavior. I'm also curious why.
Upvotes: 1