Merge pull request #2278 from edx/cdodge/session-inactivity-timeout
add middleware to be able to expire inactive sessions after N seconds
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
"""
|
||||
This test file will test registration, login, activation, and session activity timeouts
|
||||
"""
|
||||
import time
|
||||
|
||||
from django.test.utils import override_settings
|
||||
from django.core.cache import cache
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
|
||||
from contentstore.tests.utils import parse_json, user, registration, AjaxEnabledTestClient
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
@@ -188,6 +194,29 @@ class AuthTestCase(ContentStoreTestCase):
|
||||
|
||||
# Logged in should work.
|
||||
|
||||
@override_settings(SESSION_INACTIVITY_TIMEOUT_IN_SECONDS=1)
|
||||
def test_inactive_session_timeout(self):
|
||||
"""
|
||||
Verify that an inactive session times out and redirects to the
|
||||
login page
|
||||
"""
|
||||
self.create_account(self.username, self.email, self.pw)
|
||||
self.activate_user(self.email)
|
||||
|
||||
self.login(self.email, self.pw)
|
||||
|
||||
# make sure we can access courseware immediately
|
||||
resp = self.client.get_html('/course')
|
||||
self.assertEquals(resp.status_code, 200)
|
||||
|
||||
# then wait a bit and see if we get timed out
|
||||
time.sleep(2)
|
||||
|
||||
resp = self.client.get_html('/course')
|
||||
|
||||
# re-request, and we should get a redirect to login page
|
||||
self.assertRedirects(resp, settings.LOGIN_REDIRECT_URL + '?next=/course')
|
||||
|
||||
|
||||
class ForumTestCase(CourseTestCase):
|
||||
def setUp(self):
|
||||
|
||||
@@ -174,6 +174,9 @@ MIDDLEWARE_CLASSES = (
|
||||
|
||||
# catches any uncaught RateLimitExceptions and returns a 403 instead of a 500
|
||||
'ratelimitbackend.middleware.RateLimitMiddleware',
|
||||
|
||||
# for expiring inactive sessions
|
||||
'session_inactivity_timeout.middleware.SessionInactivityTimeout',
|
||||
)
|
||||
|
||||
############# XBlock Configuration ##########
|
||||
|
||||
53
common/djangoapps/session_inactivity_timeout/middleware.py
Normal file
53
common/djangoapps/session_inactivity_timeout/middleware.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
Middleware to auto-expire inactive sessions after N seconds, which is configurable in
|
||||
settings.
|
||||
|
||||
To enable this feature, set in a settings.py:
|
||||
|
||||
SESSION_INACTIVITY_TIMEOUT_IN_SECS = 300
|
||||
|
||||
This was taken from StackOverflow (http://stackoverflow.com/questions/14830669/how-to-expire-django-session-in-5minutes)
|
||||
"""
|
||||
from datetime import datetime, timedelta
|
||||
from django.conf import settings
|
||||
from django.contrib import auth
|
||||
|
||||
LAST_TOUCH_KEYNAME = 'SessionInactivityTimeout:last_touch'
|
||||
|
||||
|
||||
class SessionInactivityTimeout(object):
|
||||
"""
|
||||
Middleware class to keep track of activity on a given session
|
||||
"""
|
||||
def process_request(self, request):
|
||||
"""
|
||||
Standard entry point for processing requests in Django
|
||||
"""
|
||||
if not hasattr(request, "user") or not request.user.is_authenticated():
|
||||
#Can't log out if not logged in
|
||||
return
|
||||
|
||||
timeout_in_seconds = getattr(settings, "SESSION_INACTIVITY_TIMEOUT_IN_SECONDS", None)
|
||||
|
||||
# Do we have this feature enabled?
|
||||
if timeout_in_seconds:
|
||||
# what time is it now?
|
||||
utc_now = datetime.utcnow()
|
||||
|
||||
# Get the last time user made a request to server, which is stored in session data
|
||||
last_touch = request.session.get(LAST_TOUCH_KEYNAME)
|
||||
|
||||
# have we stored a 'last visited' in session? NOTE: first time access after login
|
||||
# this key will not be present in the session data
|
||||
if last_touch:
|
||||
# compute the delta since last time user came to the server
|
||||
time_since_last_activity = utc_now - last_touch
|
||||
|
||||
# did we exceed the timeout limit?
|
||||
if time_since_last_activity > timedelta(seconds=timeout_in_seconds):
|
||||
# yes? Then log the user out
|
||||
del request.session[LAST_TOUCH_KEYNAME]
|
||||
auth.logout(request)
|
||||
return
|
||||
|
||||
request.session[LAST_TOUCH_KEYNAME] = utc_now
|
||||
@@ -1,3 +1,9 @@
|
||||
"""
|
||||
This test file will run through some LMS test scenarios regarding access and navigation of the LMS
|
||||
"""
|
||||
import time
|
||||
from django.conf import settings
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test.utils import override_settings
|
||||
|
||||
@@ -37,6 +43,28 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
self.create_account(username, email, password)
|
||||
self.activate_user(email)
|
||||
|
||||
@override_settings(SESSION_INACTIVITY_TIMEOUT_IN_SECONDS=1)
|
||||
def test_inactive_session_timeout(self):
|
||||
"""
|
||||
Verify that an inactive session times out and redirects to the
|
||||
login page
|
||||
"""
|
||||
email, password = self.STUDENT_INFO[0]
|
||||
self.login(email, password)
|
||||
|
||||
# make sure we can access courseware immediately
|
||||
resp = self.client.get(reverse('dashboard'))
|
||||
self.assertEquals(resp.status_code, 200)
|
||||
|
||||
# then wait a bit and see if we get timed out
|
||||
time.sleep(2)
|
||||
|
||||
resp = self.client.get(reverse('dashboard'))
|
||||
|
||||
# re-request, and we should get a redirect to login page
|
||||
self.assertRedirects(resp, settings.LOGIN_REDIRECT_URL + '?next=' + reverse('dashboard'))
|
||||
|
||||
|
||||
def test_redirects_first_time(self):
|
||||
"""
|
||||
Verify that the first time we click on the courseware tab we are
|
||||
|
||||
@@ -654,6 +654,9 @@ MIDDLEWARE_CLASSES = (
|
||||
|
||||
# For A/B testing
|
||||
'waffle.middleware.WaffleMiddleware',
|
||||
|
||||
# for expiring inactive sessions
|
||||
'session_inactivity_timeout.middleware.SessionInactivityTimeout',
|
||||
)
|
||||
|
||||
############################### Pipeline #######################################
|
||||
|
||||
Reference in New Issue
Block a user