2

我有一个 jquery 日历小部件,可以查询服务器上的多个事件源,这些源都返回相同的 JSON 格式响应。

真正令人讨厌的是,当用户 cookie 过期时,这些来源都会将用户重定向到返回 HTML 内容的登录页面。

我用 fiddler 查看了请求,我可以看到两个请求已完成:第一个是来自 jquery 日历对象的请求,用于更新具有 http 状态 302 的事件,并在请求登录页面后立即使用 http 状态 200。

GET /xyz/Adempimenti/GetEvents?_=1289170335910&start=1288566000&end=1291590000 HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Accept: application/json, text/javascript, */*; q=0.01

HTTP/1.1 302 Found
Cache-Control: private
Content-Type: text/html; charset=utf-8
Location: /xyz/Login/LogOn?ReturnUrl=%2fxyz%2fAdempimenti%2fGetEvents%3f_%3d1289170335910%26start%3d1288566000%26end%3d1291590000&_=1289170335910&start=1288566000&end=1291590000

我的网站深深地基于 ajax 调用,而这个日历只是解释我面临的问题的一个例子。我想避免在每次 ajax 调用时处理错误并进行重定向。最佳方法是找到一种在用户会话 cookie 过期时自动断开用户连接的方法。我已经在一些网络电子邮件系统中看到了这一点,该系统会自动创建一个对话框,说明会话已过期。

对这个方向有帮助吗?

4

2 回答 2

4

当 jQuery 执行 AJAX 请求时,它会发送HTTP_X_REQUESTED_WITH标头。

您是否考虑过在服务器端检查该标头?如果会话超时,您可以返回包含“请登录”错误消息的 JSON 结构,而不是重定向到登录页面。

那将是我眼中最干净的方法。

另一个想法是在执行“真正的”请求之前发出额外的 Ajax 请求。如果第一个请求失败或text/html返回内容类型,您就知道您不再登录。不是很优雅但比尝试在客户端计算会话持续时间更容易(这肯定是不可靠的)。

于 2010-11-07T23:48:44.643 回答
1

我相信您正在处理一个会话,其超时信息存储在服务器端(客户端不一定知道他的会话何时不再有效)。获取该信息并将其与请求一起发送给客户端。一个简单的setTimeout(notifySessionExpiration, sessTimeout * 1000)就可以了。

回答外围问题:

$ajax = isset($_SERVER['HTTP_X_REQUESTED_WITH']) && 
($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')

$ajax如果您正在处理 XML 请求,则将设置为 true,假设浏览器发送兼容的标头(现在它往往会这样做)。

您可能希望隔离发送 302 的代码部分(可能是一个应用程序范围的控制器,用于处理基于会话获取用户的个人信息),如果$ajax为真,则将异常放在一起。您可能希望发回 401 或 403,然后让您的 Javascript 回调以特定方式响应该状态(例如,重定向到登录页面或提供弹出式 Ajax 登录覆盖)。

如果这只是一个玩具网站,并且您愿意亲自动手创建一个更强大的解决方案,我可以提出以下建议。

  • 不要使用语义上误导的 XHR 检测器:在我看来,向不同的请求者提供不同的内容是完全合理的,如果它是对请求者进行特定调整的相同内容(例如,浏览器怪癖)。但是当一个特定的请求者具有根本不同的功能角色时(例如,当一个 XHR 被发送以期待 JSON/XML 响应与浏览器发送一个正常的 HTML 的 HTTP 请求时),那么该请求不应该用于相同的资产。在我看来,最佳实践是为.html或无扩展路径生成 HTML,例如GET /mypage.htmlor GET /mypage,而 XHR 定制的内容应该是GET /mypage.jsonorGET /mypage.xml性质。这并不是说 XHR永远不应该获得 HTML 响应。有时,它非常适合,例如当您为登录表单加载 HTML 片段时,或者如果您只是使用 AJAX 进行页面转换。
  • 实现一个系统来保持会话活动:如果您必须让会话按时间单独过期,而不是一直持续到浏览器关闭,那么在会话过期之前进行客户端调用以使用简单的 AJAX 请求刷新会话(如果页面关闭,则不会触发请求,允许会话在分配的时间过去时过期)。
于 2010-11-08T00:18:16.880 回答