当SessionMiddleware被激活时,每个HttpRequest对象 - 任何Django视图函数的第一个参数 - 将具有会话属性,这是一个类似字典的对象。 您可以阅读并在您的视图中的任何位置写入request.session。 您也可以多次编辑它。
所有会话对象都从基类backends.base.SessionBase继承。 它有以下标准字典方法:
- getitem(key)
- setitem(key, value)
- delitem(key)
- contains(key)
- get(key, default=None)
- pop(key)
- keys()
- items()
- setdefault()
- clear()
它也有这些方法:
flush()
从会话中删除当前会话数据并删除会话cookie。如果要确保先前的会话数据不能从用户的浏览器再次访问(例如,django.contrib.auth.logout()函数调用它),则使用此选项。
set_test_cookie()
设置测试Cookie以确定用户的浏览器是否支持Cookie。由于Cookie的工作方式,您将无法在用户的下一页请求之前对其进行测试。请参阅“设置测试cookie”
以下更多信息。
test_cookie_worked()
根据用户的浏览器是否接受测试Cookie,返回True或False。由于Cookie的工作方式,您必须在先前的单独页面请求中调用set_test_cookie()。有关更多信息,请参见下面的“设置测试cookie”。
delete_test_cookie()
删除测试cookie。用它来清理你自己。
set_expiry(value)
设置会话的到期时间。您可以传递许多不同的值:
-
如果value是一个整数,那么会话将在多秒钟不活动之后过期。
例如,调用request.session.set_expiry(300)会使会话在5分钟内过期。 -
如果value是日期时间或timedelta对象,则会话将在该特定日期/时间过期。 请注意,如果您使用PickleSerializer,则datetime和timedelta值仅可序列化。
-
如果值为0,则用户的会话cookie将在用户的Web浏览器关闭时到期。
-
如果值为无,会话将恢复为使用全局会话到期策略。
阅读会话不被视为有效到期的活动。 会话过期是从上次会话被修改时计算出来的。
get_expiry_age()
返回此会话到期之前的秒数。 对于没有自定义到期的会话(或设置为在浏览器关闭时过期的会话),这将等于SESSION_COOKIE_AGE。 该函数接受两个可选的关键字参数:
-
modification:会话的最后修改,作为日期时间对象。 默认为当前时间。
-
expiry:会话的到期信息,作为日期时间对象,int(以秒为单位)或None。 如果存在一个值,则默认为set_expiry()存储在会话中的值,或者是None。
get_expiry_date()
返回此会话过期的日期。 对于没有自定义到期的会话(或设置为在浏览器关闭时过期的会话),这将等于从现在开始的SESSION_COOKIE_AGE秒。 该函数接受与get_expiry_age()相同的关键字参数。
get_expire_at_browser_close()
返回True或False,取决于用户的Web浏览器关闭时用户的会话Cookie是否过期。
clear_expired()
从会话存储中删除过期的会话。 这个类方法由clearsessions调用。
cycle_key()
在保留当前会话数据的同时创建新的会话密钥。 django.contrib.auth.login()调用此方法来减轻会话固定。
会话对象准则
- 使用普通的Python字符串作为request.session上的字典键。 这是一个比硬性规定更重要的惯例。
- 以下划线开头的会话字典键由Django保留供内部使用。
- 不要用新对象重写request.session,也不要访问或设置它的属性。 像Python字典一样使用它。
会话序列化
在版本1.6之前,Django默认使用pickle将会话数据序列化,然后将其存储在后端。如果您使用的是经过签名的cookie会话后端,并且SECRET_KEY被攻击者所知(在Django中没有可能导致其泄漏的固有漏洞),攻击者可以在会话中插入一个字符串,该字符串在取消时会执行服务器上的任意代码。这样做的技术很简单,并且可以在互联网上轻松获得。
尽管cookie会话存储器会对cookie存储的数据进行签名以防止篡改,但SECRET_KEY泄漏会立即升级为远程执行代码的漏洞。这种攻击可以通过使用JSON而不是pickle序列化会话数据来缓解。为了实现这一点,Django 1.5.3引入了一个新的设置SESSION_SERIALIZER来定制会话序列化格式。为了向后兼容,此设置默认使用Django 1.5.x中的django.contrib.sessions.serializers.PickleSerializer,但为了加强安全性,默认为从Django 1.6开始的django.contrib.sessions.serializers.JSONSerializer。
即使在自定义序列化器中描述的警告中,我们强烈建议坚持使用JSON序列化,特别是如果您使用的是Cookie后端。
捆绑的序列
serializers.JSONSerializer
来自django.core.signing的JSON序列化程序包装。只能序列化基本数据类型。此外,由于JSON仅支持字符串键,请注意,在request.session中使用非字符串键将无法按预期工作:
>>> # initial assignment
>>> request.session[0] = 'bar'
>>> # subsequent requests following serialization &
deserialization
>>> # of session data
>>> request.session[0] # KeyError
>>> request.session['0']
'bar'
有关JSON序列化限制的更多详细信息,请参阅custom-serializers部分。
serializers.PickleSerializer
支持任意的Python对象,但是如上所述,如果攻击者知道SECRET_KEY,则可能导致远程执行代码漏洞。
编写你自己的序列
请注意,与PickleSerializer不同,JSONSerializer无法处理任意Python数据类型。通常情况下,便利性和安全性之间有一个折衷。如果您希望在JSON支持的会话中存储更高级的数据类型(包括日期时间和Decimal),则需要编写自定义序列化程序(或在将这些值存储到request.session中之前将这些值转换为JSON可序列化对象)。
虽然序列化这些值非常简单(django.core.serializers.json.DateTimeAwareJSONEncoder可能会有所帮助),但编写一个可以可靠地取回与放入的东西相同的解码器会更脆弱。例如,您冒着返回日期时间的风险,该日期时间实际上是恰好与日期时间相同的格式的字符串)。
您的序列化程序类必须实现两种方法,分别转储(self,obj)和加载(self,data)以序列化和反序列化会话数据字典。
设置测试Cookie
为了方便起见,Django提供了一种简单的方法来测试用户的浏览器是否接受cookie。只需在视图中调用request.session的set_test_cookie()方法,然后在后续视图中调用test_cookie_worked(),而不是在同一视图调用中调用。
由于cookie的工作方式,set_test_cookie()和test_cookie_worked()之间的这种尴尬分裂是必要的。当你设置一个cookie时,你不能确定浏览器是否接受它,直到浏览器的下一个请求。最好使用delete_test_cookie()来清理自己。在您验证测试cookie正常工作后执行此操作。
以下是一个典型的使用示例:
def login(request):
if request.method == 'POST':
if request.session.test_cookie_worked():
request.session.delete_test_cookie()
return HttpResponse("You're logged in.")
else:
return HttpResponse("Please enable cookies and try again.")
request.session.set_test_cookie()
return render_to_response('foo/login_form.html')
网友评论