响应内容类型与预期不同

发布于 2024-10-01 01:39:17 字数 907 浏览 4 评论 0原文

我有一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

真心难拥有 2024-10-08 01:39:17

当 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).

二智少女猫性小仙女 2024-10-08 01:39:17

我相信您正在处理一个会话,其超时信息存储在服务器端(客户端不一定知道他的会话何时不再有效)。获取该信息并将其与请求一起发送给客户端。一个简单的 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< /code>,而 XHR 定制的内容应具有 GET /mypage.jsonGET /mypage.xml 性质。这并不是说 XHR 永远不应该获得 HTML 响应。有时,它是非常合适的,例如当您加载登录表单的 HTML 代码片段时或者您只是使用 AJAX 进行页面转换时。
  • 实施一个系统来保持会话处于活动状态:如果您必须让会话仅按时间过期而不是仅仅持续到浏览器关闭,则可以进行客户端调用以刷新会话过期之前的简单 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:

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

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.

  • Don't use a semantically misleading XHR detector: in my opinion, delivering different content to different requesters is perfectly reasonable if it's the same-ish content with specific adaptations for the requester (e.g., browser quirks). But when a particular requester has a fundamentally different functional role (e.g., when an XHR gets sent in expecting a JSON/XML response vs. when a browser sends in a normal HTTP request for HTML), then the request shouldn't be for the same asset. The best practice, in my opinion, is to produce HTML for .html or extension-less paths, for instance GET /mypage.html or GET /mypage, whereas XHR-tailored content should be of the GET /mypage.json or GET /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.
  • Implement a system to keep your session alive: if you must have your session expire by time alone rather than just lasting until the browser is closed, then put in a client-side call to refresh the session with a simple AJAX request before it expires (if the page is closed, the request isn't fired, allowing the session to expire when the allotted time passes).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文