响应内容类型与预期不同
我有一个 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 过期时自动断开用户连接的方法。我已经在一些网络电子邮件系统中看到了这种实现,该系统会自动创建一个对话框,表示会话已过期。
对这个方向有帮助吗?
I have a jquery calendar widget that do query several event sources on the server and these sources all returns the same JSON format responses.
What is really annoying is that when the user cookie expires these sources all redirect the user to the login page returning HTML content.
I have looked at the request with fiddler and I can see two request done: first one is a request from the jquery calendar object to update the events with http status 302 and immediately after a request to the login page with http status 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
My site is deeply based on ajax calls and this one of the calendar is just an example to explain the problem i am facing to. I would like to avoid to handle the error on every ajax call and do a redirect. The optimal way would be to find a way to automatically disconnect the user when his session cookie expires. I have seen this implemented in some web email system that automatically create a dialog saying that the session has expired.
Any help on this direction?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当 jQuery 执行 AJAX 请求时,它会发送
HTTP_X_REQUESTED_WITH
标头。您是否考虑过在服务器端检查该标头?如果会话超时,您可以返回包含“请登录”错误消息的 JSON 结构,而不是重定向到登录页面。
这将是我眼中最干净的方法。
另一种想法是在执行“真正的”请求之前发出额外的 Ajax 请求。如果第一个请求失败或返回
text/html
内容类型,您就知道您不再登录。不是很优雅,但比尝试计算客户端的会话持续时间更容易(这是绑定的)变得不可靠)。When jQuery does an AJAX request, it sends the
HTTP_X_REQUESTED_WITH
header.Have you considered checking for that header on server side? If the session has timed out, instead of redirecting to the login page, you could return a JSON structure containing the "please log in" error message.
That would be the cleanest method in my eyes.
Another idea would be to make an additional Ajax request before doing the "real" one. If the first request fails or gets a
text/html
content type back, you know you are no longer logged in. Not very elegant but easier than trying to count the session duration on client side (which is bound to be unreliable).我相信您正在处理一个会话,其超时信息存储在服务器端(客户端不一定知道他的会话何时不再有效)。获取该信息并将其与请求一起发送给客户端。一个简单的
setTimeout(notifySessionExpiration, sessTimeout * 1000)
就可以解决问题。回答外围问题:
如果您正在处理 XML 请求,则将
$ajax
设置为 true,假设浏览器发送兼容的标头(现在通常这样做)。您可能需要隔离发送 302 的代码部分(可能是一个应用程序范围的控制器,负责根据会话获取用户的个人信息),并在
$ajax
的情况下组合一个异常真的。您可能想要发回 401 或 403,然后让 Javascript 回调以特定方式响应该状态(例如,重定向到登录页面或提供弹出 Ajax 登录覆盖层)。如果这只是一个玩具网站,并且您愿意亲自动手创建更强大的解决方案,我可以提出以下建议。
.html
或无扩展名路径生成 HTML,例如GET /mypage.html
或GET /mypage< /code>,而 XHR 定制的内容应具有
GET /mypage.json
或GET /mypage.xml
性质。这并不是说 XHR 永远不应该获得 HTML 响应。有时,它是非常合适的,例如当您加载登录表单的 HTML 代码片段时或者您只是使用 AJAX 进行页面转换时。I believe you're dealing with a session, whose timeout information is stored server-side (the client doesn't necessarily know when his session will no longer be valid). Get that information and send it to the client with the request. The a simple
setTimeout(notifySessionExpiration, sessTimeout * 1000)
will do the trick.To answer peripheral questions:
Will set
$ajax
to true if you're dealing with an XML request, assuming the browser sends compliant headers (which it tends to do these days).You will probably want to isolate the part of your code that sends the 302 (perhaps an application-wide controller that handles fetching the user's personal information based on the session) and put together an exception if
$ajax
is true. You'd probably want to send back a 401 or 403 and then have your Javascript callback respond to that status in a particular way (e.g., redirecting to login page or providing an popup Ajax login overlay).If this is just a toy site and you're willing to get your hands dirty to create a more robust solution, I can make the following recommendations.
.html
or extension-less paths, for instanceGET /mypage.html
orGET /mypage
, whereas XHR-tailored content should be of theGET /mypage.json
orGET /mypage.xml
nature. This is not to say that XHR should never get an HTML response. Sometimes, it's perfectly appropriate, like when you're loading an HTML snippet for a login form or if you're just using AJAX for page transitions.