访问控制允许来源与CORS问题和HTTPS重定向(IIS/IISNode /的NodeJS)

问题描述:

我有一个Web应用程序,它由两个部分组成:访问控制允许来源与CORS问题和HTTPS重定向(IIS/IISNode /的NodeJS)

  • 总部设在角的“前端”( Chrome会)在本地主机上运行:8000
  • 的“后端”立足ExpressJS /的NodeJS,在本地主机上运行:3000

在试图逐步转换为完全使用HTTPS应用,我想它会首先转换后端更好。我已经构建它,以便我可以切换在后端启用/禁用HTTPS的功能。

我已经设置了后台运行:

  • 有两个下IIS绑定:http和https
  • IISNode下的应用程序的NodeJS。

问题来了,当我尝试运行整个应用程序(前端和后端)在本地主机在本地的发展环境,但与HTTP到HTTPS的重写(重定向)规则。之后,我在前端收到CORS错误。

总之,在我的本地开发环境,我试图:

Basic App

阅读所有的东西CORS了几个小时后,我调整基于this blog post web.config中和的applicationHost.config和this * article试图捕获请求源标头值。这是他们的样子。

的applicationHost.config包含此部分:

<location path="Default Web Site"> 
    <system.webServer> 
     <rewrite> 
      <allowedServerVariables> 
       <add name="CAPTURED_ORIGIN" /> 
       <add name="RESPONSE_Access-Control-Allow-Origin" /> 
      </allowedServerVariables> 
     </rewrite> 
    </system.webServer> 
</location> 

这里是我的的Web.config

<?xml version="1.0" encoding="utf-8"?> 
<!-- 
    This configuration file is required if iisnode is used to run node processes behind 
    IIS or IIS Express. For more information, visit: 

    https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/web.config 
--> 

<configuration> 
    <system.webServer> 
    <handlers> 

     <!-- Indicates that the server.js file is a node.js site to be handled by the iisnode module --> 
     <add name="iisnode" path="bin/www" verb="*" modules="iisnode" /> 
    </handlers> 
    <rewrite> 
     <rules> 
     <rule name="Capture Origin Header"> 
      <match url=".*" /> 
      <conditions> 
       <add input="{HTTP_ORIGIN}" pattern=".+" /> 
      </conditions> 
      <serverVariables> 
       <set name="CAPTURED_ORIGIN" value="{C:0}" /> 
      </serverVariables> 
      <action type="None" /> 
     </rule> 

     <!-- HTTP-to-HTTPS redirect --> 
       <rule name="Redirect to HTTPS" enabled="true" stopProcessing="true"> 
        <match url="(.*)" ignoreCase="true" /> 
      <conditions logicalGrouping="MatchAll" trackAllCaptures="true"> 
         <add input="{HTTPS}" pattern="^off$" /> 
         <add input="{HTTP_HOST}" pattern="([^/:]*?):[^/]*?" /> 
      </conditions>     
         <action type="Redirect" url="https://{C:1}:3443/{R:0}" appendQueryString="true" redirectType="Temporary" /> 
       </rule> 

     <!-- First we consider whether the incoming URL matches a physical file in the /public folder --> 
     <rule name="StaticContent"> 
      <action type="Rewrite" url="public{REQUEST_URI}" /> 
     </rule> 

     <!-- All other URLs are mapped to the node.js site entry point --> 
     <rule name="DynamicContent"> 
      <conditions> 
      <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" /> 
      </conditions> 
      <action type="Rewrite" url="bin/www" /> 
     </rule> 
     </rules> 
     <outboundRules> 
     <rule name="Set-Access-Control-Allow-Origin for known origins"> 
      <match serverVariable="RESPONSE_Access-Control-Allow-Origin" pattern=".+" negate="true" /> 
      <action type="Rewrite" value="{CAPTURED_ORIGIN}" /> 
     </rule> 
     </outboundRules>  
    </rewrite> 

    <!-- Make sure error responses are left untouched --> 
    <httpErrors existingResponse="PassThrough" /> 

    </system.webServer> 
    <appSettings> 
    <add key="HTTPS_ENABLED" value="true" /> 
    </appSettings> 
</configuration> 

的应用程序的NodeJS还设立了处理从本地主机CORS :8000,localhost:3000,localhost:3443(本地https)和“null”(转换为字符串)。 (更多的是,后来)

但是,如果我用这个配置,然后我得到的前端以下错误:

的XMLHttpRequest不能加载 http://localhost:3000/foo/bar/的预检 响应无效(重定向)

我怀疑这是因为IIS处理重定向,但结果是处理前检查(HTTP选项),无效响应(重定向)。然而,根据this * article,并@sideshowbarker答案,使我相信,铬,59.0.3071.104的当前版本,应该能够处理从CORS预检OPTIONS请求的HTTP重定向响应。

如果我删除从的applicationHost.config服务器变量和HTTP到HTTPS的重写和其他规则,并从网络。配置,然后添加代码,允许的NodeJS应用程序来处理重定向到HTTPS,然后将修改后的应用程序如下:(?的NodeJS IIS)

Revised App

随后便出现一个未知的发生是由于服务器错误该请求被取消:

Chrome Dev Tools Networking 1

Chrome Dev Tools Networking 2

您可以在Chrome中看到撤销://网内部/#事件甚至ŧ霍夫在响应报头的请求,并且所述访问控制允许来源起源匹配:

Chrome net-internals

有(即使一个正由客户端接收的)没有有用的错误消息,这导致我相信它是IIS,而不是NodeJS取消请求并返回没有有用的信息。

我最终在NodeJS Lite服务器(而不是IIS作为实验)下运行时添加了一个“null”条目来处理CORS,但我需要在IIS/IISNode下运行该条目。但是,那么IIS/IISNode/NodeJS组合似乎存在问题。

我怀疑是“空”的请求源是最有可能的一个请求,该服务器执行重定向的结果,因为你真的有两个要求: - 从浏览器 的原始请求 - 该请求是重定向的结果 发生重定向时,我假设重定向请求中的原点与原始URL不同,并且由于https://www.w3.org/TR/cors/#generic-cross-origin-request-algorithms中所述的原因,重定向内的Origin请求标头为空。

但是,这并不能解释为什么当我让NodeJS处理重定向时,Origin请求和Access-Control-Allow-Origin响应标头值都为空,并且请求仍然被取消。 : -/

最后,如果我消除了HTTP到HTTPS重定向的任何尝试,那么应用程序在我的开发环境中工作正常。

+0

https://*.com/questions/42168773/how-to-resolve-preflight-is-无效重定向在Cors/42172732#42172732是不同的情况。对于预检OPTIONS本身的响应必须始终是20倍的成功响应,例如200或204.对预检本身的响应永远不可能是重定向302或其他。规范禁止这一点。但是您提出请求的服务器正在响应这样的重定向;因此你看到的错误信息。因此,唯一的解决方案是修复服务器,使得您不需要该OPTIONS请求的重定向响应。 – sideshowbarker

+0

@sideshowbarker我想知道你是否会出现。你以前的回应的粉丝。 :-)那么,当使用HTTP到HTTPS重写规则时,似乎某些Web服务器(IIS)被破坏了?这是我不明白的部分。使用IIS重写规则,我的理解是,对浏览器没有立即响应,但服务器重定向,然后提供响应。这是我感到困惑的。您是否在尝试处理CORS预检请求时无法使用HTTPS重定向规则? – jhenderson2099

+0

@sideshowbarker - 也是您在https://*.com/questions/42168773/how-to-resolve-preflight-is-invalid-redirect-in-cors/42172732#42172732的回复表示“浏览器未遵循重定向对于CORS预检不再符合规范,但浏览器需要更新他们的实现以符合规范更改“这就是让我相信3xx回复正常的原因 – jhenderson2099

对预印OPTIONS本身的响应本身必须始终是2xx成功响应,例如200或204.对印前检查本身的响应永远不会是重定向 - 例如302.规范禁止这样做。

但问题中引用的响应显示服务器响应这样的重定向;因此引用了错误消息。如果浏览器获得对预检OPTIONS请求的3xx响应,该规范要求浏览器停在那里 - 将预检视为失败。

所以唯一的解决办法是修复服务器,因此它不会给那个OPTIONS的重定向响应。


CORS request with Preflight and redirect: disallowed. Workarounds?问题中描述的重定向和预检有一种不同的情况。在这种情况下,这是发生了什么:

OPTIONS /documents/123 --> 204 (everything okay, please proceed) 
GET /documents/123  --> 303 redirect to `/documents/abc` 

也就是说,到OPTIONS请求本身的响应是一个2xx成功,但到前端代码发送后继实际请求的响应是一个3XX。

针对该方案,该规范以前需要浏览器停止,不要让前端代码使得能够获得响应请求,浏览器将通过类似的错误回应:

请求被重定向到'http://localhost:3000/foo/bar/', ,这是不允许需要预检的跨源请求。

注意这比列举了在问题方案中的错误信息,这是不同的:

的XMLHttpRequest无法加载预检http://localhost:3000/foo/bar/响应 无效(重定向)

在那种情况(问题中的那个),而是发生了什么:

OPTIONS /documents/123 --> 307 redirect to `/documents/abc` 

也就是说,对OPTIONS本身的响应是3xx。该规范仍然需要预检失败。

但是,对于其他不允许用于需要预检的跨源请求的情况下,规范不再需要失败,并且该错误不应再发生在浏览器中; the spec changed in August 2016 to no longer require it,并且随后更新所有浏览器引擎以匹配该更改。

铬是实现更新的最后一个浏览器,但it was fixed in the Chrome sources in December 2016,并运在Chrome修复57