如何解决“预检无效(重定向)”或“预检请求不允许重定向”
Posted
技术标签:
【中文标题】如何解决“预检无效(重定向)”或“预检请求不允许重定向”【英文标题】:How to resolve 'preflight is invalid (redirect)' or 'redirect is not allowed for a preflight request' 【发布时间】:2022-01-18 15:49:26 【问题描述】:我已按照此步骤设置我的服务器以启用 CORS。 https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
但现在在我的浏览器开发控制台中,我看到了以下错误消息:
XMLHttpRequest 无法加载 https://serveraddress/abc。回应 预检无效(重定向)
你知道我能做些什么来解决它吗?我正在 HTTPS 中发出 CORS 请求。我认为这导致“预检无效(重定向)”失败。但我不知道重定向 OPTIONS 请求的原因或内容。
谢谢。
【问题讨论】:
【参考方案1】:简答:确保代码中的请求 URL 不缺少尾部斜杠。
缺少尾随斜杠问题是问题中引用的错误的最常见原因。
但这不是唯一的原因——只是最常见的原因。继续阅读以了解更多详情。
当您看到此错误时,这意味着您的代码正在触发您的浏览器发送CORS preflight OPTIONS
request,并且服务器以3xx
重定向响应。为避免该错误,您的请求需要获得2xx
成功响应。
您可以调整您的代码以避免触发浏览器发送OPTIONS
请求。
就本例中发生的情况而言,重要的是要知道浏览器会在以下情况下进行 CORS 预检:
请求方法不是GET
、HEAD
或POST
您设置了除Accept
、Accept-Language
、Content-Language
、Content-Type
、DPR
、Downlink
、Save-Data
、Viewport-Width
或 @987654338 之外的自定义请求标头
Content-Type
请求标头的值不是application/x-www-form-urlencoded
、multipart/form-data
或text/plain
如果您无法更改代码以避免浏览器需要进行预检,另一种选择是:
-
在对
OPTIONS
请求的响应中检查Location
响应标头中的URL。
更改您的代码以直接向其他 URL 发出请求。
网址之间的区别可能很简单,例如路径中的尾部斜杠 - 例如,您可能需要更改代码中的网址以添加尾部斜杠 - 例如,http://localhost/api/auth/login/
(请注意尾部斜杠) 而不是 http://localhost/api/auth/login
(没有尾部斜杠)——或者您可能需要删除尾部斜杠。
您可以使用浏览器开发工具中的网络窗格来检查对OPTIONS
请求的响应,并在Location
响应标头的值中找到重定向 URL。
但是,在某些情况下,以下所有情况都是正确的:
你无法避免预检OPTIONS
您无法对请求 URL 进行任何调整
您无法将请求 URL 替换为完全不同的 URL
这些情况的常见情况是当您尝试使用某些需要 OAuth 或 SSO 工作流程的第三方端点,而该工作流程不打算从前端代码中使用。
在这种情况下——实际上在所有情况下——必须认识到,对预检的响应必须来自您的前端代码向其发送请求的同一来源。
因此,即使您创建了一个您可以控制的服务器端代理:
-
如果您的浏览器向您的代理发送预检
OPTIONS
请求。
您已配置代理,使其仅将请求重定向到第 3 方端点。
因此,您的前端最终会直接从该第 3 方端点接收响应。
…那么预检将失败。
在这种情况下,最终您唯一的选择是:确保预检不只是重定向到第 3 方端点,而是您自己的服务器端(代理)代码接收来自该端点的响应,使用它,然后将自己的响应发送回您的前端代码。
【讨论】:
感谢您的回答。我会听从你的建议。我的应用程序需要将 Content-Type application/json 发送到服务器,以便触发预飞行。我无法改变这一点。 我知道已经有好几年了,但今天这对我有帮助。我的问题是缺少尾部斜杠。谢谢! 好的有用的信息永远不会过时。 太棒了,我一直被这个问题困扰,你的回答对我帮助很大! Content-Type 请求标头的值不是 [...] 这不是那么简单(没有双关语):twitter.com/jub0bs/status/1432025056234835980【参考方案2】:首先,确保标题中有“Access-Control-Allow-Origin”:“*”
然后只需删除 url 末尾的“/”
例如改变
url: "https://facebook/api/login/"
进入
url: "https://facebook/api/login" (without '/')
【讨论】:
仅当您希望您的端点对所有人开放时才执行此操作。您可以通过添加以下内容来允许您自己的域(和子域): SetEnvIf Origin "^(.*\.domain\.com)$" ORIGIN_SUB_DOMAIN=$1 Header set Access-Control-Allow-Origin "%ORIGIN_SUB_DOMAINe " env=ORIGIN_SUB_DOMAIN"Access-Control-Allow-Origin": "*"
这可能是生产中的安全风险,但对于开发来说没关系。【参考方案3】:
就我而言,我不必将请求标头设置为“Access-Control-Allow-Origin”:“*”。网址必须以“/”结尾
【讨论】:
【参考方案4】:当您尝试将 https 服务调用为 http 时,有时会发生这种情况,例如,当您在以下位置执行请求时:
'http://example.com/api/v2/tickets'
应该是:
'https://example.com/api/v2/tickets'
【讨论】:
以上是关于如何解决“预检无效(重定向)”或“预检请求不允许重定向”的主要内容,如果未能解决你的问题,请参考以下文章
CORS:对预检请求的响应未通过访问控制检查:预检请求不允许重定向
从源 xxxx 访问 XMLHttpRequest ' 被 CORS 策略阻止:对预检的响应。预检请求不允许重定向