【问题标题】:how to implement enhanced session handling in PHP如何在 PHP 中实现增强的会话处理
【发布时间】:2010-05-10 10:37:41
【问题描述】:

我正在使用 PHP 中的会话,并且我在单个域上有不同的应用程序。问题是,cookie 是特定于域的,因此会话 ID 会发送到单个域上的任何页面。 (我不知道是否有办法让 cookie 以不同的方式工作)。所以会话变量在这个域的每个页面中都是可见的。 我正在尝试实现自定义会话管理器来克服这种行为,但我不确定我是否考虑正确。

我想完全避免 PHP 会话系统,并创建一个全局对象,该对象将存储会话数据并在脚本结束时将其保存到数据库。

  1. 在第一次访问时,我会生成唯一的 session_id 并创建一个 cookie
  2. 在脚本结束时,使用 session_id 保存会话数据、会话开始和上次访问的时间戳,以及来自 $_SERVER 的数据,例如 REMOTE_ADDR、REMOTE_PORT、HTTP_USER_AGENT。
  3. 在每次访问时检查从客户端发送的 cookie 中的 session_id 数据库,检查 IP、端口和用户代理(出于安全考虑)并将数据读入会话变量(如果未过期)。
  4. 如果 session_id 过期,从数据库中删除。

那个会话变量将被实现为单例(我知道我会与这个类紧密耦合,但我不知道更好的解决方案)。

我正在尝试获得以下好处:

  • 会话变量在同一服务器和同一域上的其他脚本中不可见
  • 会话过期的自定义管理
  • 查看打开会话的方式(类似于在线用户列表)

我不确定我是否忽略了此解决方案的任何缺点。有没有更好的办法?

谢谢!!

更新: 我没有足够详细地解释它并在这里造成了很多混乱,所以我想更清楚地说明我在处理什么:

我正在构建 SOA 服务器应用程序,它将部署在许多不同的环境中。它没有自己的网络服务器,因此在这些环境中可能会有另一个 PHP 应用程序。这些公司的员工将在此应用程序中拥有用户帐户,因此他们将在此应用程序中获取带有会话 ID 的 cookie。

正如我们所知,在加载会话数据时运行 PHP 的网络服务器并没有区别(至少默认情况下)哪个脚本从哪个目录创建会话。它只需要一个会话 ID。此会话 ID 随从客户端到服务器的每个请求一起发送。从您的回答中,我找到了一种方法,PHP 如何限制某些目录的 cookie,但恶意用户能够编辑 cookie,因为它存储在他的计算机中。在我的情况下,恶意用户可以访问在同一环境中编写和执行 php 脚本,尽管无法访问我的应用程序及其数据库。如果他创建一个脚本,他可以使用我的应用程序的 cookie 中的 Session id,因此他可以读取和编辑我的应用程序上的会话数据并访问我的应用程序的某些部分,他不应该被允许。

我发现在这样的环境中部署应用程序会存在另一个安全威胁,我想要的是我能做的最好的隔离,默认会话处理似乎太危险了,不适合这样的用途。

所以我的问题是,如果你看到的东西在我的设计中不太安全、不太灵活,而不是默认会话管理。

谢谢你的回答,..

【问题讨论】:

  • 锁定 IP 地址和端口不是一个好主意。因为通常两者都可以从请求到请求而变化。
  • 我不知道端口,但我读过某种 PHP 安全书籍,你不应该允许来自不同 IP 的请求,因为窃取会话 ID 和IP限制应该避免使用这个被盗的id。我知道在某些情况下可能会更改您的 ip,但您知道这些情况是什么情况吗?
  • 一些 ISP 为每个请求分配一个新 IP。
  • 是的,谢谢,但我认为为更改 IP 的用户设置例外情况可能会更安全,对于 IP 不变的用户来说,禁止 IP 切换应该是件好事。好吧,谢谢,它需要正确调整:)

标签: php session


【解决方案1】:

你需要使用:

session_set_cookie_params()

http://www.php.net/manual/en/function.session-set-cookie-params.php

特别是您需要在每个 web 应用程序中设置“路径”。

【讨论】:

  • 是的,我忽略了这个 :) 谢谢,.. 但是当我现在考虑它时,从安全的角度来看,如果您将该 cookie(修改为在其他目录中工作)发送到另一个该服务器上的应用程序,该应用程序将访问该会话数据。
  • 每个应用都会给出不同的 session_id。所以他们不能访问彼此的数据。但是,您可能仍有一些使用默认“/”路径的旧会话数据,因此一旦所有应用程序都已修复,您需要清除浏览器上的 cookie。
  • 确保你在 before session_start() 之前调用它
  • 每个应用都会给你不同的 sessId,但是如果你将一个 sessId 传递给另一个应用(我的意思是故意编辑 cookie),php 将读取该会话的数据,并且不会关心哪个应用创建了那个会话。这对我来说很危险,因为在我的工作场所,同事将有权访问我的 web 应用程序,但无法访问代码和数据库。但他们可以访问同一网络服务器上的不同文件夹。我不希望他们从我的 webapp 中获取 sessId,在他们的 php 脚本中使用它来访问和修改会话数据,并获得对他们不应该访问的应用程序部分的访问权。这是一个复杂的问题,我很抱歉 :)
【解决方案2】:

看看 PHP 中的 session_set_save_handler 方法。

http://php.net/manual/en/function.session-set-save-handler.php

好吧,事实上,有几家公司使用自定义会话处理程序的方法来处理多域、分布式内存/数据库支持的会话处理

【讨论】:

  • 是的,我做到了,但我认为这并不能解决我的主要问题,即跨域的会话变量可见性。
【解决方案3】:

如果您不希望共享会话出现问题,您可以使用session_save_path 函数设置应用程序保存会话文件的路径。由于它不会被服务器上的其他应用程序使用,因此您不会遇到会话共享问题。

只有一件事:确保您保存会话文件的路径不能从网络访问。类似的东西:

/YourAppFolder
     /www (web accessible)
     / libs
     /config
     / session (where you put your session files)

【讨论】:

    【解决方案4】:

    您可以查看以下内容:

    • 设置会话 ID 的路径和域。如果域是 .mastergaurav.com,cookie 将被发送回 mastergaurav.com、www.mastergaurav.com、blogs.mastergaurav.com 等
    • 可能不是使用会话 ID 作为 cookie - 如果您必须真正遍历多个 TLD 域 - 将其作为完全自定义实施的 URL 的一部分:
      abcd.php?<?php echo session_name(); ?>=<?php echo session_id(); ?>&domain=<your-domain>

    【讨论】:

    • 我不认为你有我的问题。我不处理多个域/子域,即使我是,我认为它不会解决我的任何子问题
    【解决方案5】:

    我不确定我是否忽略了此解决方案的任何缺点。有没有更好的办法?

    它非常复杂 - 而且它不会工作,例如remote_port 将在请求之间更改,remote_addr 可能会更改。

    至少有 2 个非常明显的解决方案,而无需重新发明会话处理的工作方式:

    1) 在每个应用中为会话使用不同的 cookie 名称 - 请参阅 session_name()

    2) 将每个应用程序放在不同的子目录中(例如 http://example.com/app1/http://example.com/app2/、...)并在 cookie 上设置路径 - 请参阅 session_set_cookie_params 或为 session.cookie_path 使用不同的 ini 设置

    【讨论】:

    • 好吧,检查 IP 地址和端口不是必不可少的功能,所以它不会成为我设计的失败点。我可以用它来分析潜在的攻击,我可以限制选定的用户只使用特定范围的 IP 地址,我可以随意使用这些信息,而且我可能根本不使用它。您的解决方案适用于这些 cookie,但即使您从 app1 劫持 cookie 并将其发送到 app2,我也不希望会话变量在其他应用程序中可见。也许克服这一点并不难,但它不会给我带来另一个优势,比如更好的过期 mngmt。
    • 方法 1 确实会跨应用程序公开会话 ID。方法2没有。您如何使会话数据过期与您如何使用户与会话协调无关 - 您对会话过期的建议是什么,这在任何方面都比默认方法更好? (除了为此维护自己的代码的风险增加外,我认为没有区别)。
    • 我没有说它会暴露会话 ID。我试图解释一个攻击场景以更新我的问题。会话过期 - 我已经要求让某些用户的会话在很短的时间后过期。它必须是灵活的,因此来自公司 IP 范围的连接不需要像来自外部的连接一样快地过期。对于某些用户,它可能根本不会从某些 IP 过期。我们不要质疑这样做的安全性,但总的来说,拥有这种灵活性可能非常有用
    【解决方案6】:

    我想完全避免 PHP 会话系统,并创建一个全局对象,该对象将存储会话数据并在脚本结束时将其保存到数据库。

    如果您正在考虑序列化您的对象,我不建议您这样做,因为它不是保存安全细节的好习惯。

    http://www.php.net/manual/en/function.session-set-save-handler.php#81761

    看看上面的例子,他给出了一个很好的解决方案。

    跨域维护您的状态。

    1. 首先生成一个唯一标识符。
    2. 您可以创建在每次访问页面时读取的 cookie。在每个页面访问时,cookie 都会从浏览器发送到服务器。
    3. 如果您想要另一种方法而不是 cookie,您还可以将您的唯一标识符作为您生成的每个 URL 的一部分传递。

    更新:

    1. 首先,您需要根据 IP 地址限制用户访问您的应用程序,如果您想让应用程序更安全,可以通过 crossdomain.xml 限制用户来实现。

    2. 您需要检查会话的加密,这样即使用户将其破解,他也无法使用它。数据应使用私钥加密并使用公钥解密。握手基于公钥。

    【讨论】:

    • 我不明白你的意思是“不保存安全细节”。我不会存储用户密码,因为它没有任何用途,但所有其他敏感数据,在其之上是一个构建的应用程序,已经在数据库中,所以我认为这不会降低安全性.我要存储的只是会话数据-登录的用户以及一些会话设置。也许我应该提到它是一个 SOA 服务器。
    • 如果您存储会话信息并在每次访问时重新连接,它可能会占用您的数据库,并且您的数据必须定期清理。
    • 连接应该在请求之间打开,并且只在每次访问时发送查询。 PHP 会话默认使用文件,但也可以切换到数据库。在这种情况下,它与内置的数据库会话处理完全相同,对于文件,我认为它是网络服务器的开销。据我所知,数据库针对这种数据访问进行了更好的优化。此外,这两种方式都需要定期清理。有什么办法可以避免这种情况?
    • 数据库可以为此进行很好的优化。为避免这种情况,您需要使用 cookie,正如我之前所说的,您的 cookie 从浏览器发送到服务器。当您的用户从一个域跳转到另一个域时,获取 cookie 数据,将其传递到新域,最后使用 cookie 数据重新发布。
    • 我认为我们在这里并不了解对方。我有 1 个域,上面有更多应用程序。一个应用程序是我构建的,其他应用程序应尽可能隔离。我在对 Foo 的回答的评论中对其进行了更多解释。
    猜你喜欢
    • 1970-01-01
    • 2018-07-12
    • 1970-01-01
    • 2013-03-24
    • 2012-12-24
    • 1970-01-01
    • 2012-07-06
    • 2018-01-24
    • 2012-02-08
    相关资源
    最近更新 更多