想象一下,每次浏览到另一个页面时,您都必须重新登录到网站,或者您最喜欢的网站忘记了所有设置,并且每次访问时都必须重新输入它们。
现代网站无法提供我们习惯的可用性和便利性,而无法以某种方式记住您是谁以及您之前在网站上的活动。在设计上,HTTP是无状态的 - 在一个请求和下一个请求之间不存在持久性,并且服务器无法判断连续请求是否来自同一个人。
这种缺少状态是使用会话进行管理的,会话是浏览器和Web服务器之间的半永久性双向通信。当你访问一个现代化的网站时,在大多数情况下,Web服务器将使用匿名会话来跟踪与访问相关的数据。会话被称为匿名,因为网络服务器只能记录你做了什么,而不是你是谁。
当我们稍后返回电子商务网站时,我们都遇到过这种情况,并发现我们放入购物车的物品仍然存在,尽管没有提供任何个人详细信息。
会话通常会使用经常被恶意但很少理解的Cookie持续存在。像所有其他Web框架一样,Django也使用Cookie,但是以更聪明和安全的方式进行操作,就像您将看到的一样。
Django全面支持匿名会话。会话框架允许您以每个站点访问者为基础存储和检索任意数据。它将数据存储在服务器端,并提取Cookie的发送和接收。 Cookie包含会话ID - 不是数据本身(除非您使用基于cookie的后端);比其他一些框架更安全的实现cookie。
启用会话
会话通过一个中间件来实现。由django-admin startproject创建的默认settings.py已经激活了SessionMiddleware。要启用会话功能,请编辑MIDDLEWARE_CLASSES设置并确保它包含'django.contrib.sessions.middleware.SessionMiddleware'。
如果您不想使用会话,则最好从MIDDLEWARE_CLASSES和INSTALLED_APPS中的“django.contrib.sessions”中删除SessionMiddleware行。它会为你节省一点点的开销。
配置会话引擎
默认情况下,Django将会话存储在数据库中(使用模型django.contrib.sessions.models.Session)。尽管这很方便,但在某些设置中,将会话数据存储在别处会更快,因此可以将Django配置为将会话数据存储在文件系统或缓存中。
使用数据库支持的会话
如果您想使用数据库支持的会话,则需要将'django.contrib.sessions'添加到INSTALLED_APPS设置中。配置安装后,运行manage.py migrate以安装存储会话数据的单个数据库表。
使用缓存会话
为了获得更好的性能,您可能需要使用基于缓存的会话后端。要使用Django的缓存系统存储会话数据,首先需要确保已经配置了缓存;详细信息请参阅缓存文档。
如果您使用Memcached缓存后端,则只应使用基于缓存的会话。 本地内存高速缓存后端不会保留足够长的数据作为一个好选择,并且直接使用文件或数据库会话会更快,而不是通过文件或数据库高速缓存后端发送所有内容。 此外,本地内存缓存后端不是多进程安全的,因此可能不是生产环境的理想选择。
如果您在CACHES中定义了多个高速缓存,则Django将使用默认高速缓存。 要使用另一个缓存,请将SESSION_CACHE_ALIAS设置为该缓存的名称。 一旦你的缓存配置完毕,你有两个选择如何将数据存储在缓存中:
- 为简单的缓存会话存储设置SESSION_ENGINE为“django.contrib.sessions.backends.cache”。 会话数据将直接存储在缓存中。 但是,会话数据可能不是持久性的:如果缓存填满或缓存服务器重新启动,缓存数据可能会被逐出。
- 对于持久的缓存数据,请将SESSION_ENGINE设置为“django.contrib.sessions.backends.cached_db”。 这使用直写式高速缓存 - 每写入高速缓存也将写入数据库。 如果数据尚未存在于缓存中,则会话读取仅使用数据库。
两个会话存储都非常快,但简单缓存更快,因为它忽略了持久性。 在大多数情况下,cached_db后端将足够快,但是如果您需要性能的最后一点,并且愿意让会话数据不时被删除,那么缓存后端就是为您服务的。 如果您使用cached_db会话后端,则还需要遵循使用数据库支持的会话的配置说明。
使用基于文件的会话
要使用基于文件的会话,请将SESSION_ENGINE设置为“django.contrib.sessions.backends.file”。 您可能还想设置SESSION_FILE_PATH设置(默认从tempfile.gettempdir()输出,很可能是/ tmp)来控制Django存储会话文件的位置。 务必检查您的Web服务器是否有权读取和写入此位置。
使用基于Cookie的会话
要使用基于cookie的会话,请将SESSION_ENGINE设置为“django.contrib.sessions.backends.signed_cookies”。 会话数据将使用Django的加密签名工具和SECRET_KEY设置进行存储。
建议将SESSION_COOKIE_HTTPONLY设置设置为True,以防止从JavaScript访问存储的数据。
如果SECRET_KEY不保密并且您正在使用PickleSerializer,则可能导致任意远程代码执行。
拥有SECRET_KEY的攻击者不仅可以生成伪造的会话数据,您的站点将信任该数据,还可以远程执行任意代码,因为数据是使用pickle序列化的。 如果您使用基于Cookie的会话,请特别注意您的密钥始终保持完全保密,以供任何可能远程访问的系统使用。
会话数据已签名但未加密
当使用cookies后端时,会话数据可以被客户端读取。 MAC(消息认证码)用于保护数据免受客户端的改变,以便会话数据在被篡改时将失效。 如果存储cookie的客户端(例如您的用户的浏览器)无法存储所有会话cookie并丢弃数据,则会发生同样的失效。 尽管Django压缩数据,但仍然完全有可能超过每个cookie 4096个字节的常见限制。
没有及时性保证
还要注意的是,虽然MAC可以保证数据的真实性(数据是由您的网站而不是其他人生成的),数据的完整性(数据的完整性和正确性),但它不能保证数据的及时性,即 你正在被送回你发给客户的最后一件东西。 这意味着对于会话数据的某些用途,cookie后端可能会让您重新开始重放攻击。 与其他会话后端不同,后者保留每个会话的服务器端记录,并在用户注销时使其失效,而当用户注销时,基于cookie的会话不会失效。 因此,如果攻击者窃取用户的cookie,即使用户注销,他们也可以使用该cookie作为该用户登录。 如果Cookie比您的SESSION_COOKIE_AGE年龄大,则只会将其检测为“陈旧”。
最后,假设上述警告并未阻止您使用基于Cookie的会话:Cookie的大小也会影响您网站的速度。
网友评论