【问题标题】:Do AJAX requests retain PHP Session info?AJAX 请求是否保留 PHP 会话信息?
【发布时间】:2010-10-15 04:18:42
【问题描述】:

如果我有一个用户登录到我的网站,他的 id 存储在$_SESSION 中,然后从他的浏览器中单击“保存”按钮,该按钮将向服务器发出 AJAX 请求。他的$_SESSION 和cookie 是否会保留在此请求中,我是否可以安全地依赖$_SESSION 中存在的ID?

【问题讨论】:

    标签: php ajax session


    【解决方案1】:

    答案是肯定的:

    会话在服务器端维护。就服务器而言,AJAX 请求和常规页面请求没有区别。它们都是 HTTP 请求,并且它们都以相同的方式在 header 中包含 cookie 信息。

    从客户端,无论是常规请求还是 AJAX 请求,都将始终将相同的 cookie 发送到服务器。 Javascript 代码不需要做任何特殊的事情,甚至不需要意识到这种情况的发生,它的工作方式与处理常规请求相同。

    【讨论】:

    • 后续:服务器可以在设置cookie时设置HttpOnly标志,这意味着您的Javascript将无法看到cookie。但是,仍然会为 AJAX 和常规页面请求发送 cookie ,并继续以完全相同的方式工作。您的 Javascript 在 document.cookie 中看不到它。
    • 如果打开了 PHP 错误报告,您会得到一个会话错误,并通过 AJAX 响应返回。我最近在项目中间歇性地收到Warning: session_write_close(): Failed to write session data (user) 错误,但仅在加载页面其余部分期间发生 AJAX 请求时。我正在为会话数据使用 MySQL 数据库,并且主页请求可能会锁定该表,从而阻止 AJAX 请求访问它。
    • @ButtleButkus 这听起来像是您的服务器端代码中的一个问题,我相信如果您将其作为自己的问题提交,人们会愿意提供帮助。您不应该仅仅因为您将 MySQL 用于会话而收到该错误,因为它不应该以一种会因错误而失败的方式锁定。这可能是 MySQL 连接饱和的问题,或者是其他一些不相关的问题。
    • 这发生在一台 vagrant 机器上,所以 MySQL 连接应该是饱和的。如果我不能很快弄清楚,我肯定会发布一个问题。
    【解决方案2】:

    如果 AJAX 请求的 PHP 文件具有session_start(),则将保留会话信息。 (禁止请求在同一个域内)

    【讨论】:

    • 确实,这就是我忘记做的:-)
    【解决方案3】:

    您真正了解的是:cookie 是否与 AJAX 请求一起发送?假设 AJAX 请求是针对同一个域(或在 cookie 的域约束内),答案是肯定的。因此,返回到同一服务器的 AJAX 请求确实保留了相同的会话信息(假设被调用的脚本发出 session_start() 就像任何其他想要访问会话信息的 PHP 脚本一样)。

    【讨论】:

    • 我可能错了,但我认为甚至不可能将 ajax 请求发布到其他域(不包括子域)?
    • 你也许可以用动态脚本技巧作弊。不过从不累。
    • 是的,无法向其他域发出 ajax 请求。但是,您可以在页面中动态插入
    • 无法向其他域发出 ajax 请求。但你可以在你的 php 代码中创建一个代理。 ajax 请求到代理,代理请求到其他域。
    • 请注意... ajax 请求可以跨域进行,但前提是响应类型为 jsonp。我一直这样做。
    【解决方案4】:

    嗯,并非总是如此。 使用 cookie,你很好。但是“我可以安全地依赖存在的 id” 敦促我用一个重要的观点来扩展讨论(主要是为了参考,因为这个页面的访问者人数似乎很高)。

    PHP 可以配置为通过 URL 重写而不是 cookie 来维护会话。 (How it's good or bad (separate question,现在让我们坚持当前的,只有一个旁注:基于 URL 的会话最突出的问题 --裸会话 ID 的明显可见性——这不是内部 Ajax 调用的问题;但是,如果它为 Ajax 启用,它也会为站点的其余部分启用,所以...)

    在 URL 重写(无 cookie)会话的情况下,Ajax 调用必须自己处理,确保它们的请求 URL 正确制作。 (或者您可以推出自己的自定义解决方案。在要求不高的情况下,您甚至可以诉诸维护会话 on the client side。)如果不使用 cookie,则需要明确注意会话连续性:

    1. 如果 Ajax 仅从 HTML 逐字调用 extract URL(从 PHP 接收),那应该没问题,因为它们已经煮熟了(嗯,煮熟了)。

    2. 如果他们需要自己组装请求 URI,则需要手动将会话 ID 添加到 URL。 (查看here,或者PHP生成的页面源(with URL-rewriting on)看看怎么做。)


    来自OWASP.org

    实际上,Web 应用程序可以使用两种机制,cookie 或 URL 参数,甚至从一个切换到另一个(自动 URL 重写)如果满足某些条件(例如,存在 不支持 cookie 或不支持 cookie 的 Web 客户端 出于用户隐私考虑而接受)。

    来自Ruby-forum 帖子:

    当使用 php 和 cookie 时,会话 ID 将自动在请求标头中发送,即使是 Ajax XMLHttpRequests。 如果你 使用或允许基于 URL 的 php 会话,您必须添加会话 ID 到每个 Ajax 请求 url。

    【讨论】:

    • 关于有多少人禁用了 session cookie 的任何可靠统计数据? (我没有找到任何东西。仅在 Javascript 上:这在美国/欧洲似乎约为 2%,世界平均约为 1.2%。)
    • URL 上的会话 ID 已过时,insecure 做法。在当今的网络上,没有人应该假设他们可以在禁用 cookie 的情况下进行冲浪,并且仍然可以登录他们拥有帐户的网站。如果您的一位访问者禁用了 cookie,则可以安全地假设 a) 他们出于隐私原因特别不想在任何网站上登录;或者 b) 他们不小心这样做了,现在他们无法登录到任何网站,而不仅仅是您的网站。
    【解决方案5】:

    AJAX 请求保留会话非常重要。最简单的示例是当您尝试对管理面板执行 AJAX 请求时,比如说。当然,您将保护您提出请求的页面,而不是其他没有管理员登录后获得会话的人访问的页面。 有意义吗?

    【讨论】:

      【解决方案6】:

      有一点需要注意,特别是如果您使用的是框架,那就是检查应用程序是否在请求之间重新生成会话 id - 任何显式依赖于会话 id 的东西都会遇到问题,尽管显然其余的会话中的数据不受影响。

      如果应用程序正在像这样重新生成会话 ID,那么您最终可能会遇到这样的情况,即 ajax 请求实际上使请求页面中的会话 ID 无效/替换。

      【讨论】:

        【解决方案7】:

        这就是框架所做的,例如如果您在 Front Controller 或 boostrap 脚本中初始化会话,您将不必关心页面控制器或 ajax 控制器的初始化。 PHP 框架不是万能药,但它们可以做很多这样有用的事情!

        【讨论】:

          【解决方案8】:

          将您的 session() 身份验证放入所有接受 ajax 请求的服务器端页面:

          if(require_once("auth.php")) {
          
          //run json code
          
          }
          
          // do nothing otherwise
          

          这是我做过的唯一方法。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-19
            • 1970-01-01
            • 2021-12-06
            • 1970-01-01
            • 1970-01-01
            • 2017-12-27
            • 1970-01-01
            相关资源
            最近更新 更多