使用Django会话来存储登录用户

时间:2012-12-31 05:02:32

标签: django session nosql django-sessions

我正在创建一个以REST为中心的应用程序,它将为大多数特定于域的模型使用某种NoSQL数据存储。对于我打算围绕REST数据框架构建的主站点,我仍然希望将传统的关系数据库用于用户,计费信息以及域数据模型范围之外的其他元数据。

我被告知,如果我可以尽可能避免在同一请求上对RDBMS和NoSQL数据存储执行I / O,那么这种方法只是个好主意。

我的问题:

  1. 这是一个好建议吗? (我这样假设,但如果第一个前提是错误的话,其余的这些问题都是无用的。)
  2. 我想尽可能多地缓存登录用户。是否可以使用Django会话以安全,可靠,正确和容错的方式执行此操作?理想情况下,我希望会话API是一个安全的替代品,可以用尽可能少的与users表的交互来检索当前用户。我需要做些什么来完成任务?
  3. 如果这样做太麻烦了,那么在不使用django-nonrel的情况下将用户信息存储在NoSQL存储中(即完全消除RDBMS)是多么容易?自定义身份验证/授权后端可以执行此操作吗?

1 个答案:

答案 0 :(得分:6)

我正在考虑对我的应用程序使用相同的方法,我认为它通常是安全的,但需要特别注意解决缓存一致性问题。

Django正常运行的方式是,当收到请求时,将对Session表运行查询,以查找与请求中的cookie相关联的会话。然后,当您访问request.user时,将针对User表运行查询以查找给定会话的用户(如果有的话,因为Django支持匿名会话)。因此,默认情况下,Django需要两个查询来将每个请求与用户相关联,这很昂贵。

关于Django会话的一个好处是它可以用作键值存储而不扩展任何模型类(不像例如很难用其他字段扩展的User类)。因此,您可以将request.session['email'] = user.email放在会话中存储其他数据。从某种意义上说,这是安全的,你从request.session词典中读到的内容肯定是你放在那里的,客户无法改变这些值。因此,您确实可以使用此技术来避免查询User表。

为避免查询Session表,您需要启用会话缓存(或使用django.contrib.sessions.backends.signed_cookies在客户端cookie中存储会话数据,这是安全的,因为此类cookie受加密保护,不会被客户端修改)。

启用缓存后,您需要0次查询才能将请求与用户数据相关联。但问题是缓存一致性。如果使用带有直写选项(django.core.cache.backends.locmem.LocMemCachedjango.contrib.sessions.backends.cached_db)的本地内存缓存,会话数据将在每次修改时写入数据库,但如果是,则不会从数据库中读取数据存在于缓存中。如果您有多个Django进程,这会引发一个问题。如果一个进程修改了一个会话(例如更改session['email']),则其他进程仍然可以使用旧的缓存值。

您可以使用共享缓存(Memcached后端)来解决它,这可以保证一个进程所做的更改对所有其他进程都可见。通过这种方式,您将查询替换为具有对Memcached后端的请求的Session表,这应该快得多。

将会话数据存储在客户端cookie中也可以解决缓存一致性问题。如果您修改cookie中的电子邮件字段,则客户端发送的所有未来请求都应该有一封新电子邮件。虽然客户可以故意发送旧cookie,但仍然带有旧值。这是否是一个问题取决于应用程序。