我正在考虑对我的应用程序使用相同的方法,我认为它通常是安全的,但需要特别注意解决缓存一致性问题。
Django 正常操作的方式是,当收到请求时,会针对 Session 表运行查询,以从请求中找到与 cookie 关联的会话。然后,当您访问时request.user
,将对 User 表运行查询以查找给定会话的用户(如果有,因为 Django 支持匿名会话)。因此,默认情况下,Django 需要两个查询来将每个请求与一个用户相关联,这很昂贵。
Django session 的一个好处是它可以用作键值存储,而无需扩展任何模型类(与难以使用附加字段扩展的 User 类不同)。因此,您可以request.session['email'] = user.email
在会话中存储其他数据。从某种意义上说,这是安全的,您从request.session
字典中读取的内容肯定是您放在那里的内容,客户端无法更改这些值。因此,您确实可以使用这种技术来避免查询 User 表。
为避免查询 Session 表,您需要启用会话缓存(或使用 将会话数据存储在客户端 cookie 中django.contrib.sessions.backends.signed_cookies
,这是安全的,因为此类 cookie 受到加密保护,不会被客户端修改)。
启用缓存后,您需要 0 个查询才能将请求与用户数据相关联。但问题是缓存一致性。如果您使用带有 write through 选项 ( django.core.cache.backends.locmem.LocMemCache
with django.contrib.sessions.backends.cached_db
) 的本地内存缓存,则会话数据将在每次修改时写入 DB,但如果它存在于缓存中,则不会从 DB 中读取。如果您有多个 Django 进程,这会带来一个问题。如果一个进程修改了会话(例如更改session['email']
),其他进程仍然可以使用旧的缓存值。
您可以通过使用共享缓存(Memcached 后端)来解决它,它保证一个进程所做的更改对所有其他进程都是可见的。通过这种方式,您将使用对 Memcached 后端的请求替换对 Session 表的查询,这应该更快。
在客户端 cookie 中存储会话数据也可以解决缓存一致性问题。如果您修改 cookie 中的电子邮件字段,则客户端发送的所有未来请求都应该有一个新的电子邮件。虽然客户端可以故意发送一个旧 cookie,它仍然带有旧值。这是否是一个问题取决于应用程序。