$_SESSION 是跨多个页面安全传输数据的正确方法吗?

Is $_SESSION a proper way to transport data across many pages securely?

我正在制作的应用程序要求用户根据其用户类型和权限在登录时获得不同的内容。多个页面都需要在登录时从他们那里检索到的信息。

我的想法是创建一个名为 'users' 的 class,在登录时创建一个实例,使用数据库设置它的所有属性,然后将 $_SESSION 设置为此对象以便可以访问它跨网站创建所需的显示。

这是正确且安全的做法吗?

一如既往,实施细节最为重要。通常,使用会话来持久化与用户登录会话相关的状态是可以的,实际上,这就是会话的目的。但是,有一些注意事项。

对象和序列化

只要你在会话中存储一个对象,它就会被序列化,而当你读回它时,它就会被反序列化。这适用于简单的值对象,但如果您的 class 包含文件或数据库 link 引用等内容,则可能无效。在最坏的情况下和特殊情况下,这甚至可能导致安全问题,但实际上不太可能发生。但是序列化本身可能很容易在某些对象上失败。

会话存储

您的会话存储有多种选择。它可以是你的 application/web 服务器内存,你的服务器可以将会话内容保存到文件中,或者将它们存储在 SQL 或 NoSQL 数据库中,等等。对会话存储的访问控制是关键,任何有权访问会话存储的人都可以修改任何用户的会话内容。比如Redis经常被用来存储session数据,但是Redis的访问控制不是很强。此外,如果会话数据存储在 Web 服务器上,则服务器上的任何管理员实际上都可以无限制地访问任何已登录用户的会话,这可能会也可能不会成为问题,具体取决于您的情况。

缓存失效问题

如果您只查询一次数据库并在第一次查询后将数据存储在会话中,那么您实质上是在将会话用作缓存,并伴随着所有相关问题。从安全角度来看,其中最重要的可能是缓存失效。假设您在登录时存储用户对会话的访问权限,这样您就不必再查询它们了。如果用户登录并保持他的会话很长时间(只要您的绝对会话超时允许,如果有的话),但同时他的访问权限发生变化,最重要的是,如果权限被撤销怎么办?您在会话中的缓存将无效,除非您设计使缓存无效的逻辑,这对于某些会话存储来说可能非常困难,并且对于更简单的存储来说仍然很复杂。减轻这种风险的一种方法是实施强制注销,但这也会对您使用的会话存储产生影响。

与会话相关的应用程序漏洞

想到的另一个威胁是,由于源代码中的安全缺陷,您的应用程序可能允许用户在某种程度上编辑会话内容。如果您将整个对象存储在会话中并且不再查询数据库,则此类漏洞可能允许攻击者提升他的特权并获得他不应该访问的东西的访问权限。显然,这种允许编辑会话内容的漏洞的可能性可能不是很高,如果存在这种漏洞,如果它在每次请求时都转向数据库,也会影响您的应用程序。但是,在后一种情况下,这种攻击的影响可能会更小。

结论

将用户对象存储在会话中并非天生不安全。 如果您减轻或接受风险,则可以这样做。 但是,您应该了解上面详述的问题,并自行决定它们是否对您的应用程序构成真正的风险,以及您是否可以减轻或愿意接受它们。