防止 Xmlhttprequest 的重定向

Posted

技术标签:

【中文标题】防止 Xmlhttprequest 的重定向【英文标题】:Prevent redirection of Xmlhttprequest 【发布时间】:2010-09-18 16:45:55 【问题描述】:

是否可以在发送 XMLHttpRequest-s 时阻止浏览器跟随重定向(即取回重定向状态码并自己处理)?

【问题讨论】:

【参考方案1】:

不符合the W3C standard for the XMLHttpRequest object(强调添加):

如果响应是 HTTP 重定向:

如果 Location 标头传达的 URL 的来源是同一个来源 与 XMLHttpRequest 来源和 重定向不违反无限 循环预防措施,透明 在观察的同时遵循重定向 同源请求事件规则。

他们是 considering 未来版本:

本规范不包括 以下功能正在 考虑用于未来版本 本规范:

禁用以下重定向的属性;

但latest 规范不再提及这一点。

【讨论】:

可笑的是,透明重定向涉及覆盖原始请求中设置的一些 HTTP 标头。具体来说,如果“Accept”标头设置为特定的内容类型,Firefox 在跟随重定向时无法包含此标头(这使得开发使用此标头的完全基于 REST 的 Web 服务变得更加困难......抱怨)。 更多搜索给我带来了这个相当老的错误报告:bugzilla.mozilla.org/show_bug.cgi?id=401564 同意,完全是rediculus的设计缺陷。【参考方案2】:

新的Fetch API 支持不同的重定向处理模式:followerrormanual,但是当重定向已完成时,我找不到查看新 URL 或状态码的方法取消。您可以停止重定向本身,然后它看起来像一个错误(空响应)。如果这就是您所需要的,那么您就可以开始了。 另外你应该知道通过这个 API 发出的请求是不可取消的yet。 他们现在是are。

对于XMLHttpRequest,您可以HEAD服务器并检查URL是否已更改:

var http = new XMLHttpRequest();
http.open('HEAD', '/the/url');
http.onreadystatechange = function() 
    if (this.readyState === this.DONE) 
        console.log(this.responseURL);
    
;
http.send();

您不会获得状态代码,但会找到新的 URL,而无需从中下载整个页面。

【讨论】:

有时使用OPTIONS 可能是更好的选择,反正只适用于非通用用途等。管理员已配置重定向整个站点/架构,例如 HTTP -> HTTPS【参考方案3】:

您可以使用responseURL 属性来获取重定向目标或检查响应最终是否是从您接受的位置获取的。 这当然意味着无论如何都会获取结果,但至少您可以获得有关重定向目标的必要信息,例如检测您想要丢弃响应的条件。

【讨论】:

在 IE 中不起作用 developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…【参考方案4】:

不,您在 XMLHttpRequest 公开的 API 中没有任何地方允许您覆盖其自动遵循 301 或 302 的默认行为。

如果客户端在 Windows 上运行 IE,那么您可以改用 WinHTTP 来设置一个选项来防止该行为,但这是一个非常有限的解决方案。

【讨论】:

【参考方案5】:

无法在客户端处理重定向或 302 状态,正如其他 cmets 中所回答的那样。但是,您可以防止重定向。为此,您可以使用“XMLHttpRequest”设置请求标头“X-Requested-With” xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest"); 这应该在打开之后但在发送之前完成。下面的例子

let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () 
   if (this.readyState == 4 && this.status == 200) 
         reqObj.success(JSON.parse(this.responseText))
    else if (this.status != 200) 
         reqObj.error(this.statusText)
   
;
xhttp.open(reqObj.type, reqObj.url, reqObj.async);
xhttp.setRequestHeader("X-Requested-With", "XMLHttpRequest");
xhttp.send();

【讨论】:

这是唯一可行的解​​决方案!谢谢!【参考方案6】:

我扩展了用户的答案以包括abort() 电话。当您想要的只是重定向 url 时,这似乎可以防止服务器发送太多数据。

var url = 'the url'
var http = new XMLHttpRequest();
http.open('GET', url);
http.onreadystatechange = function() 
    if (this.readyState === this.DONE) 
        console.log(this.responseURL)
        this.abort() // This seems to stop the response
    

http.send()

在现实生活中,我将上面的代码封装在一个 Promise 中,但它使代码难以阅读。

另外,我不明白为什么获取重定向 url 需要这么困难,但这是另一个时间和地点的问题。

【讨论】:

以上是关于防止 Xmlhttprequest 的重定向的主要内容,如果未能解决你的问题,请参考以下文章

防止用户直接访问 django 中的重定向 URL

防止 Django 模板表单中的重定向

在 MVC 网站中使用来自 HttpModule 的重定向,“正确”的方式

Spring Security 应用程序中的重定向循环

使用过滤器类的重定向过多

使用引导验证库防止表单提交后重定向