Ticket #10899: easy_session_manipulation_against_14099_with_tests.diff

File easy_session_manipulation_against_14099_with_tests.diff, 7.1 KB (added by prestontimmons, 5 years ago)

Patch with tests

  • django/test/client.py

    diff --git a/django/test/client.py b/django/test/client.py
    index 08e3ff6..41e0db5 100644
    a b class Client(object): 
    179179        self.cookies = SimpleCookie()
    180180        self.exc_info = None
    181181        self.errors = StringIO()
     182        self._session_store = None
    182183
    183184    def store_exc_info(self, **kwargs):
    184185        """
    class Client(object): 
    188189
    189190    def _session(self):
    190191        """
    191         Obtains the current session variables.
     192        Obtains a SessionStore containing all the current session variables.
    192193        """
    193         if 'django.contrib.sessions' in settings.INSTALLED_APPS:
    194             engine = import_module(settings.SESSION_ENGINE)
    195             cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
    196             if cookie:
    197                 return engine.SessionStore(cookie.value)
    198         return {}
     194        if self._session_store == None:
     195            if 'django.contrib.sessions' in settings.INSTALLED_APPS:
     196                cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
     197                engine = import_module(settings.SESSION_ENGINE)
     198                if cookie:
     199                    self._session_store = engine.SessionStore(cookie.value)
     200                else:
     201                    self._session_store = engine.SessionStore()
     202                    # if load() fails the cookie changes, so save() first
     203                    self._session_store.save() 
     204                    self.cookies[settings.SESSION_COOKIE_NAME] = \
     205                         self._session_store.session_key
     206            else:
     207                self._session_store = {}
     208        return self._session_store
    199209    session = property(_session)
    200210
     211    def _session_save(self):
     212        """
     213        Push the session store to the database then set the current
     214        session to None so that it is reloaded on subsquent requests.
     215        """
     216        if hasattr(self._session_store, 'modified'):
     217            if self._session_store.modified:
     218                self._session_store.save()
     219                # update the cookie in case cycle_key() was called
     220                self.cookies[settings.SESSION_COOKIE_NAME] = \
     221                     self._session_store.session_key
     222            self._session_store = None
     223
    201224    def request(self, **request):
    202225        """
    203226        The master request method. Composes the environment dictionary
    class Client(object): 
    285308        """
    286309        Requests a response from the server using GET.
    287310        """
     311        self._session_save()
    288312        parsed = urlparse(path)
    289313        r = {
    290314            'CONTENT_TYPE':    'text/html; charset=utf-8',
    class Client(object): 
    305329        """
    306330        Requests a response from the server using POST.
    307331        """
     332        self._session_save()
    308333        if content_type is MULTIPART_CONTENT:
    309334            post_data = encode_multipart(BOUNDARY, data)
    310335        else:
    class Client(object): 
    336361        """
    337362        Request a response from the server using HEAD.
    338363        """
     364        self._session_save()
    339365        parsed = urlparse(path)
    340366        r = {
    341367            'CONTENT_TYPE':    'text/html; charset=utf-8',
    class Client(object): 
    355381        """
    356382        Request a response from the server using OPTIONS.
    357383        """
     384        self._session_save()
    358385        parsed = urlparse(path)
    359386        r = {
    360387            'PATH_INFO':       urllib.unquote(parsed[2]),
    class Client(object): 
    374401        """
    375402        Send a resource to the server using PUT.
    376403        """
     404        self._session_save()
    377405        if content_type is MULTIPART_CONTENT:
    378406            post_data = encode_multipart(BOUNDARY, data)
    379407        else:
    class Client(object): 
    405433        """
    406434        Send a DELETE request to the server.
    407435        """
     436        self._session_save()
    408437        parsed = urlparse(path)
    409438        r = {
    410439            'PATH_INFO':       urllib.unquote(parsed[2]),
    class Client(object): 
    430459        user = authenticate(**credentials)
    431460        if user and user.is_active \
    432461                and 'django.contrib.sessions' in settings.INSTALLED_APPS:
    433             engine = import_module(settings.SESSION_ENGINE)
    434462
    435463            # Create a fake request to store login details.
    436464            request = HttpRequest()
    437             if self.session:
    438                 request.session = self.session
    439             else:
    440                 request.session = engine.SessionStore()
     465            request.session = self.session
    441466            login(request, user)
    442467
    443             # Save the session values.
    444             request.session.save()
    445 
    446             # Set the cookie to represent the session.
    447             session_cookie = settings.SESSION_COOKIE_NAME
    448             self.cookies[session_cookie] = request.session.session_key
    449             cookie_data = {
    450                 'max-age': None,
    451                 'path': '/',
    452                 'domain': settings.SESSION_COOKIE_DOMAIN,
    453                 'secure': settings.SESSION_COOKIE_SECURE or None,
    454                 'expires': None,
    455             }
    456             self.cookies[session_cookie].update(cookie_data)
    457 
    458468            return True
    459469        else:
    460470            return False
    class Client(object): 
    465475
    466476        Causes the authenticated user to be logged out.
    467477        """
     478        self._session_store = None
    468479        session = import_module(settings.SESSION_ENGINE).SessionStore()
    469480        session_cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
    470481        if session_cookie:
  • tests/regressiontests/test_client_regress/models.py

    diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
    index 22b59e5..9bd9134 100644
    a b class SessionTests(TestCase): 
    677677        self.assertEqual(response.status_code, 200)
    678678        self.assertEqual(response.content, 'YES')
    679679
     680    def test_session_manipulation(self):
     681        # Check that the existing documented behavior works
     682        session = self.client.session
     683        session["session_var"] = "foo"
     684        session.save()
     685
     686        response = self.client.get('/test_client_regress/check_session/')
     687        self.assertEqual(response.status_code, 200)
     688        self.assertEqual(response.content, 'foo')
     689
     690    def test_direct_session_manipulation(self):
     691        self.client.session['session_var'] = 'bar'
     692
     693        # Check that the session has been modified
     694        response = self.client.get('/test_client_regress/check_session/')
     695        self.assertEqual(response.status_code, 200)
     696        self.assertEqual(response.content, 'bar')
     697
     698        # Check that the session variable persists over login
     699        # when cycle_key() is called
     700        login = self.client.login(username='testclient', password='password')
     701        response = self.client.get('/test_client_regress/check_session/')
     702        self.assertEqual(response.status_code, 200)
     703        self.assertEqual(response.content, 'bar')
     704
     705        self.assertEqual(self.client.session.pop('session_var'), 'bar')
     706
    680707    def test_logout(self):
    681708        """Logout should work whether the user is logged in or not (#9978)."""
    682709        self.client.logout()
Back to Top