如何在 Azure App Service / Web App 上强制执行 HTTPS(无重定向,阻止 HTTP)

How to enforce HTTPS only (no redirect, block HTTP) on Azure App Service / Web App

Microsoft's own documentation on HSTS 表示以下关于 HSTS、HTTPS 重定向和 APIs:

Web APIs should either:

  • Not listen on HTTP.
  • Close the connection with status code 400 (Bad Request) and not serve the request.

… a single authenticated call to an API over HTTP has risks on insecure networks. The secure approach is to configure API projects to only listen to and respond over HTTPS.

我的结论是:APIs 不应重定向,因为客户端可能会愉快地通过 HTTP 发送敏感数据,并且由于重定向,一切都“正常工作”。即使对于浏览器和使用 HSTS 时,第一个请求(带有潜在的敏感数据)也可能使用 HTTP 完成。相反,APIs 应该使 HTTP 请求失败并仅通过 HTTPS 响应。

在花了一天的大部分时间研究这个之后,我发现在 Azure App Service / Web App 中,似乎没有简单的方法可以遵循这些建议。无论“HTTPS Only”是打开还是关闭,API 都可以通过 HTTP 调用:如果打开,它会重定向到 HTTPS,如果关闭,它完全可以使用 HTTP 而无需重定向。人们会认为有一种简单的方法可以使应用程序服务/网络应用程序仅通过 HTTPS 进行侦听。例如,如果“仅 HTTPS”按钮是 Off/Redirect/On.

文档说:

To disable HTTP redirection in an API, set the ASPNETCORE_URLS environment variable or use the --urls command line flag. For more information, see Use multiple environments in ASP.NET Core and 5 ways to set the URLs for an ASP.NET Core app by Andrew Lock.

不幸的是,这两个链接都没有描述这是否与 App Service / Web App 相关,或者环境变量应该是什么。我一直无法让它工作。这似乎还需要复制任何自定义域,迫使您记住要使环境变量与自定义域的更改保持同步。

如何使 Azure 应用服务/Web 应用仅侦听 HTTPS?

我当前的解决方法是部署以下 web.config,具有讽刺意味的是,它需要关闭“仅 HTTPS”才能使 HTTP 请求到达应用程序服务并被拒绝。但是,它确实完成了确保不会开发仅 HTTP API 客户端的工作,因为它们从一开始就无法工作。

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Disable HTTP" enabled="true" stopProcessing="true">
          <match url="(.*)" ignoreCase="false" />
          <conditions>
            <add input="{HTTPS}" pattern="off" />
            <add input="{WARMUP_REQUEST}" pattern="1" negate="true" />
            <add input="{REMOTE_ADDR}" pattern="^100?\." negate="true" />
          </conditions>
          <action type="CustomResponse" statusCode="400" statusReason="HTTPS Required" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

(条件来自 this blog post。)

如果有人有更好、更简单或更官方的方法,我会很乐意接受这个答案。另外,我不确定 WARMUP_REQUEST 部分是否有效(从其他地方复制);如果我将 CustomResponse 更改为 AbortRequest,槽交换操作失败,因为预热请求被丢弃。