我正在制作的应用程序要求用户在登录时根据用户类型和权限获取不同的内容。在登录时从他们检索的信息将需要跨越几页。
我的想法是创建一个名为'users'的类,在登录时创建实例,使用数据库设置其所有属性,然后将$ _SESSION设置为此对象,以便可以通过网站访问它以创建所需的显示。
这是一种正确而安全的做法吗?
答案 0 :(得分:3)
与往常一样,实施细节最重要。通常,使用会话来保持与用户登录会话相关的状态很好,实际上,这是会话的目的。但是,有一些警告。
无论何时将对象存储在会话中,它都会被序列化,并且只要您将其读回,它就会被反序列化。这适用于简单的值对象,但如果您的类包含文件或数据库链接引用等内容,则可能无效。在最坏的情况下,在特殊情况下,这甚至可能导致安全问题,但这实际上不太可能发生。但序列化本身可能很容易在某些对象上失败。
您的会话商店有多种选择。它可以是您的应用程序/ Web服务器内存,您的服务器可以将会话内容保存到文件,或将它们存储在SQL或NoSQL数据库等中。对会话存储的访问控制是关键,任何有权访问会话存储的人都可以修改会话任何用户的内容。例如,Redis通常用于存储会话数据,但Redis访问控制不是很强。此外,如果会话数据存储在Web服务器上,则服务器上的任何管理员都将对任何已登录用户的会话进行实际无限制访问,这可能是也可能不是问题,具体取决于您的方案。
如果您只查询数据库一次并在第一次查询后将数据存储在会话中,那么您实际上是将会话用作缓存,并且存在所有相关问题。从安全角度来看,其中最重要的可能是缓存失效。想象一下,您在登录时存储了对会话的用户访问权限,因此您不必再查询它们。如果用户长时间登录并保持其会话(如果您的绝对会话超时允许,如果有的话),但他的访问权限同时发生变化,最重要的是,如果权限被撤销,该怎么办?您在会话中的缓存将无效,除非您设计逻辑以使缓存无效,这对于某些会话存储可能非常困难,并且仍然比较容易复杂。减轻此风险的一种方法是实施强制注销,但这也会对您使用的会话存储产生影响。
另一个想到的威胁是,由于源代码中的安全漏洞,您的应用程序可能允许用户在某种程度上编辑会话内容。如果将整个对象存储在会话中并且再也不会查询数据库,则此类漏洞可能允许攻击者提升其权限并获取对其本身无法访问的内容的访问权限。显然,允许编辑会话内容的这种漏洞的可能性可能不是很高,如果存在这样的漏洞,如果它在每次请求时都转向数据库,那么这也会影响您的应用程序。但是,在后一种情况下,这种攻击的影响可能会更低。
在会话中存储用户对象本身并不安全。如果您减轻或接受风险,则可以这样做。 但是,您应该了解上述问题,并自行决定它们是否对您的应用程序构成真正的风险,以及您是否可以缓解或希望接受它们。