【发布时间】:2010-10-15 04:18:42
【问题描述】:
如果我有一个用户登录到我的网站,他的 id 存储在$_SESSION 中,然后从他的浏览器中单击“保存”按钮,该按钮将向服务器发出 AJAX 请求。他的$_SESSION 和cookie 是否会保留在此请求中,我是否可以安全地依赖$_SESSION 中存在的ID?
【问题讨论】:
如果我有一个用户登录到我的网站,他的 id 存储在$_SESSION 中,然后从他的浏览器中单击“保存”按钮,该按钮将向服务器发出 AJAX 请求。他的$_SESSION 和cookie 是否会保留在此请求中,我是否可以安全地依赖$_SESSION 中存在的ID?
【问题讨论】:
答案是肯定的:
会话在服务器端维护。就服务器而言,AJAX 请求和常规页面请求没有区别。它们都是 HTTP 请求,并且它们都以相同的方式在 header 中包含 cookie 信息。
从客户端,无论是常规请求还是 AJAX 请求,都将始终将相同的 cookie 发送到服务器。 Javascript 代码不需要做任何特殊的事情,甚至不需要意识到这种情况的发生,它的工作方式与处理常规请求相同。
【讨论】:
HttpOnly标志,这意味着您的Javascript将无法看到cookie。但是,仍然会为 AJAX 和常规页面请求发送 cookie ,并继续以完全相同的方式工作。您的 Javascript 在 document.cookie 中看不到它。
Warning: session_write_close(): Failed to write session data (user) 错误,但仅在加载页面其余部分期间发生 AJAX 请求时。我正在为会话数据使用 MySQL 数据库,并且主页请求可能会锁定该表,从而阻止 AJAX 请求访问它。
如果 AJAX 请求的 PHP 文件具有session_start(),则将保留会话信息。 (禁止请求在同一个域内)
【讨论】:
您真正了解的是:cookie 是否与 AJAX 请求一起发送?假设 AJAX 请求是针对同一个域(或在 cookie 的域约束内),答案是肯定的。因此,返回到同一服务器的 AJAX 请求确实保留了相同的会话信息(假设被调用的脚本发出 session_start() 就像任何其他想要访问会话信息的 PHP 脚本一样)。
【讨论】:
嗯,并非总是如此。 使用 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,则需要明确注意会话连续性:
如果 Ajax 仅从 HTML 逐字调用 extract URL(从 PHP 接收),那应该没问题,因为它们已经煮熟了(嗯,煮熟了)。
如果他们需要自己组装请求 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。
【讨论】:
AJAX 请求保留会话非常重要。最简单的示例是当您尝试对管理面板执行 AJAX 请求时,比如说。当然,您将保护您提出请求的页面,而不是其他没有管理员登录后获得会话的人访问的页面。 有意义吗?
【讨论】:
有一点需要注意,特别是如果您使用的是框架,那就是检查应用程序是否在请求之间重新生成会话 id - 任何显式依赖于会话 id 的东西都会遇到问题,尽管显然其余的会话中的数据不受影响。
如果应用程序正在像这样重新生成会话 ID,那么您最终可能会遇到这样的情况,即 ajax 请求实际上使请求页面中的会话 ID 无效/替换。
【讨论】:
这就是框架所做的,例如如果您在 Front Controller 或 boostrap 脚本中初始化会话,您将不必关心页面控制器或 ajax 控制器的初始化。 PHP 框架不是万能药,但它们可以做很多这样有用的事情!
【讨论】:
将您的 session() 身份验证放入所有接受 ajax 请求的服务器端页面:
if(require_once("auth.php")) {
//run json code
}
// do nothing otherwise
这是我做过的唯一方法。
【讨论】: