响应内容类型与预期不同

时间:2010-11-07 23:42:36

标签: jquery asp.net-mvc asp.net-mvc-2 session-cookies expired-sessions

我有一个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过期时自动断开用户连接的方法。我已经看到这在一些Web电子邮件系统中实现,该系统会自动创建一个对话框,说明会话已过期。

在这方面有任何帮助吗?

2 个答案:

答案 0 :(得分:4)

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

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

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

另一个想法是在执行“真实”之前创建一个额外的Ajax请求。如果第一个请求失败或返回text/html内容类型,则表示您已不再登录。不是非常优雅,但比尝试计算客户端的会话持续时间(必然不可靠)更容易。

答案 1 :(得分:1)

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

回答外围问题:

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

如果您正在处理XML请求,请将$ajax设置为true,假设浏览器发送符合标题的标题(这些日期往往会这样做)。

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

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

  • 不要使用语义错误的XHR检测器:在我看来,如果对请求者进行特定修改(例如浏览器)的内容相同,向不同的请求者提供不同的内容是完全合理的怪癖)。但是当特定请求者具有根本不同的功能角色时(例如,当期望JSON / XML响应发送XHR与浏览器发送HTML的正常HTTP请求时),则请求不应该是相同的资产。在我看来,最佳做法是为.html或无扩展路径生成HTML,例如GET /mypage.htmlGET /mypage,而XHR定制的内容应为{{1} }或GET /mypage.json性质。这并不是说XHR应该从不获得HTML响应。有时,它非常合适,例如当您为登录表单加载HTML片段或者您只是使用AJAX进行页面转换时。
  • 实施一个系统以保持会话活跃:如果您必须让您的会话单独到期,而不是仅持续到浏览器关闭,然后进行客户端调用以刷新在过期之前使用简单的AJAX请求进行会话(如果页面关闭,则不会触发请求,允许会话在分配的时间过后到期)。