diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index a86adf8..3f0b5f1 100644
a
|
b
|
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can
|
316 | 316 | SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks). |
317 | 317 | SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie. |
318 | 318 | SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only). |
| 319 | SESSION_COOKIE_HTTP_ONLY = False # Whether the session cookie should be flagged HTTPOnly (not visible to JavaScript in the web browser) |
319 | 320 | SESSION_COOKIE_PATH = '/' # The path of the session cookie. |
320 | 321 | SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. |
321 | 322 | SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether a user's session cookie expires when the Web browser is closed. |
diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py
index 57fcb90..86e5650 100644
a
|
b
|
class SessionMiddleware(object):
|
38 | 38 | request.session.session_key, max_age=max_age, |
39 | 39 | expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, |
40 | 40 | path=settings.SESSION_COOKIE_PATH, |
41 | | secure=settings.SESSION_COOKIE_SECURE or None) |
| 41 | secure=settings.SESSION_COOKIE_SECURE or None, |
| 42 | http_only=settings.SESSION_COOKIE_HTTP_ONLY or None) |
42 | 43 | return response |
diff --git a/django/http/__init__.py b/django/http/__init__.py
index 7c6b8f9..3e1e89d 100644
a
|
b
|
class HttpResponse(object):
|
336 | 336 | return self._headers.get(header.lower(), (None, alternate))[1] |
337 | 337 | |
338 | 338 | def set_cookie(self, key, value='', max_age=None, expires=None, path='/', |
339 | | domain=None, secure=False): |
| 339 | domain=None, secure=False, http_only=False): |
340 | 340 | self.cookies[key] = value |
341 | 341 | if max_age is not None: |
342 | 342 | self.cookies[key]['max-age'] = max_age |
… |
… |
class HttpResponse(object):
|
348 | 348 | self.cookies[key]['domain'] = domain |
349 | 349 | if secure: |
350 | 350 | self.cookies[key]['secure'] = True |
| 351 | if http_only: |
| 352 | self.cookies[key]['HTTPOnly'] = True |
351 | 353 | |
352 | 354 | def delete_cookie(self, key, path='/', domain=None): |
353 | 355 | self.set_cookie(key, max_age=0, path=path, domain=domain, |
diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
index 6b29b3b..74218ab 100644
a
|
b
|
Methods
|
509 | 509 | Returns ``True`` or ``False`` based on a case-insensitive check for a |
510 | 510 | header with the given name. |
511 | 511 | |
512 | | .. method:: HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None) |
| 512 | .. method:: HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, http_only=None) |
513 | 513 | |
514 | 514 | Sets a cookie. The parameters are the same as in the `cookie Morsel`_ |
515 | 515 | object in the Python standard library. |
… |
… |
Methods
|
523 | 523 | the domains www.lawrence.com, blogs.lawrence.com and |
524 | 524 | calendars.lawrence.com. Otherwise, a cookie will only be readable by |
525 | 525 | the domain that set it. |
| 526 | * Use ``http_only`` if you want the cookie to be hidden from JavaScript |
| 527 | on the web browser. Support for `HTTPOnly`_ dates back to 2002. Although |
| 528 | it isn't completely foolproof, it does make attacks harder to implement. |
526 | 529 | |
527 | 530 | .. _`cookie Morsel`: http://docs.python.org/library/cookie.html#Cookie.Morsel |
| 531 | .. _`HTTPOnly`: http://www.owasp.org/index.php/HTTPOnly |
528 | 532 | |
529 | 533 | .. method:: HttpResponse.delete_cookie(key, path='/', domain=None) |
530 | 534 | |
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index e631909..095c097 100644
a
|
b
|
Whether to use a secure cookie for the session cookie. If this is set to
|
942 | 942 | ensure that the cookie is only sent under an HTTPS connection. |
943 | 943 | See the :ref:`topics-http-sessions`. |
944 | 944 | |
| 945 | .. setting:: SESSION_COOKIE_HTTP_ONLY |
| 946 | |
| 947 | SESSION_COOKIE_HTTP_ONLY |
| 948 | ------------------------ |
| 949 | |
| 950 | Default: ``False`` |
| 951 | |
| 952 | Whether to hide the session cookie from JavaScript in most browsers. The |
| 953 | cookie can still be read in some browsers, but does provide an improved level |
| 954 | of security. |
| 955 | |
| 956 | .. _HTTPOnly cookies: http://www.owasp.org/index.php/HTTPOnly |
| 957 | |
945 | 958 | .. setting:: SESSION_EXPIRE_AT_BROWSER_CLOSE |
946 | 959 | |
947 | 960 | SESSION_EXPIRE_AT_BROWSER_CLOSE |
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
index a81f536..4c8aef6 100644
a
|
b
|
Whether to use a secure cookie for the session cookie. If this is set to
|
459 | 459 | ``True``, the cookie will be marked as "secure," which means browsers may |
460 | 460 | ensure that the cookie is only sent under an HTTPS connection. |
461 | 461 | |
| 462 | SESSION_COOKIE_HTTP_ONLY |
| 463 | ------------------------ |
| 464 | |
| 465 | Default: ``False`` |
| 466 | |
| 467 | Whether to hide the session cookie from JavaScript in most browsers. The |
| 468 | cookie can still be read in some browsers, but does provide an improved level |
| 469 | of security. |
| 470 | |
| 471 | .. _HTTPOnly cookies: http://www.owasp.org/index.php/HTTPOnly |
| 472 | |
462 | 473 | SESSION_EXPIRE_AT_BROWSER_CLOSE |
463 | 474 | ------------------------------- |
464 | 475 | |
diff --git a/tests/modeltests/httpresponse/__init__.py b/tests/modeltests/httpresponse/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modeltests/httpresponse/models.py b/tests/modeltests/httpresponse/models.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/modeltests/httpresponse/tests.py b/tests/modeltests/httpresponse/tests.py
new file mode 100644
index 0000000..7703941
-
|
+
|
|
| 1 | __test__ = {'API_TESTS':""" |
| 2 | >>> r = HttpResponse() |
| 3 | >>> r.set_cookie("aaa","AaA",path="/somewhere") |
| 4 | >>> r.cookies.output() |
| 5 | 'Set-Cookie: aaa=AaA; Path=/somewhere' |
| 6 | >>> r.set_cookie("aaa","AaA",domain="test.com",path="/somewhere") |
| 7 | >>> r.cookies.output() |
| 8 | 'Set-Cookie: aaa=AaA; Domain=test.com; Path=/somewhere' |
| 9 | >>> r.set_cookie("aaa","AaA",path="/somewhere",domain="test.com",max_age=10000,expires="Mdy, 01-Jan-2038 00:00:00 GMT",secure=True,http_only=True) |
| 10 | >>> r.cookies.output() |
| 11 | 'Set-Cookie: aaa=AaA; Domain=test.com; expires=Mdy, 01-Jan-2038 00:00:00 GMT; httponly; Max-Age=10000; Path=/somewhere; secure' |
| 12 | >>> r.cookies.clear() |
| 13 | >>> r.delete_cookie("bbb",domain="test.com",path="/") |
| 14 | >>> r.cookies.output() |
| 15 | 'Set-Cookie: bbb=; Domain=test.com; expires=Thu, 01-Jan-1970 00:00:00 GMT; Max-Age=0; Path=/' |
| 16 | |
| 17 | """} |
| 18 | |
| 19 | from django.http import HttpResponse |
| 20 | |
| 21 | if __name__ == "__main__": |
| 22 | import doctest |
| 23 | doctest.testmod() |