需要 SSL 但仍保留 asp.net 个自定义错误

Require SSL but still keep asp.net custom errors

我有 asp.net 个自定义错误,它们运行良好:

<customErrors mode="RemoteOnly" defaultRedirect="~/Error/Index/500">
  <error statusCode="403" redirect="~/Error/Index/403" />
  <error statusCode="404" redirect="~/Error/Index/404" />
  <error statusCode="500" redirect="~/Error/Index/500" />
  <error statusCode="502" redirect="~/Error/Index/502" />
  <error statusCode="503" redirect="~/Error/Index/503" />
  <error statusCode="504" redirect="~/Error/Index/504" />
</customErrors>

此外,ssl 证书已成功安装,我的站点可以通过 http 和 https 正常访问。

当我收到需要 SSL 的要求时,问题就出现了。该站点的 http link 已分发给 1000 个用户。所以我们需要将所有流向 http 地址的流量优雅地重定向到 https 主页。

我尝试使重定向正常工作的任何解决方案都会破坏自定义错误。

我有这个测试 url,它生成一个错误来测试我在 ~/error/test 的自定义错误页面。它使用 mvc 布局显示我的自定义错误页面。

无论我如何设置,一旦我在 IIS 的 SSL 设置中打开需要 SSL,如果我打开任何 http 自定义错误(以便启用 403.4 重定向),它甚至不会尝试显示我的自定义 500 页。它显示了通用的 http 500 页面。

我希望使用重定向在 http 级别处理 403.4,使用我的自定义错误页面在 asp.net 级别处理 500。顺便说一句,这不是一个页面,而是一个使用会话变量中的 .net 异常的控制器。

我怎样才能做到这一点?

问题似乎是 IIS "Requires SSL" 功能与现有链接之间的断开连接 - IIS 中的所有这一切导致它拒绝不是通过 HTTP 发出的请求,它不执行任何重定向。

403.4 是一个 custom IIS sub-status code,意思是 "SSL Required" - 如果您在没有 SSL 的情况下请求站点,您会收到该错误 - 即它会阻止所有不是在 HTTPS 下发出的请求。

发出的实际响应是标准的 403 - 禁止,不涉及重定向,也没有告诉浏览器它应该通过 SSL 请求站点的任何内容 - HTML 中的所有内容 returned,希望用户能够理解。在将请求传递给您的应用程序进行处理之前,IIS 发出了错误,这就是为什么您看不到任何自定义错误的原因 - 无论哪种方式,如果您看到错误页面,它仍然是 403 页面.

因此,如果您需要支持 HTTP 下的初始请求,则需要设置某种形式的重定向。

有几种方法可以做到这一点:

使用 UrlRewrite 模块 - 但请注意,这可能是一个单独的安装,具体取决于您的托管服务器。安装完成后,您可以执行以下操作:

<system.webServer>
    <rewrite>
        <rules>
            <rule name="RequireSsl" stopProcessing="true">
                <match url="(.*)" />
                <conditions>
                    <add input="{HTTPS}" pattern="ON" negate="true" />
                </conditions>
                <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" />
            </rule>
        </rules>
    </rewrite>
</system.webServer>

这将确保对服务器的所有请求(静态文件和 MVC 路由)都重定向到 SSL。

另一个选项是 [RequireHttps] 过滤器属性,它可以添加到控制器、操作或全局过滤器集合中,但是这主要只会影响 MVC 路由 - 静态文件仍然可以在没有 HTTPS 的情况下提供。

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    [...]
    // Add RequireHttps to any existing filters to force all routes to SSL
    filters.Add(new RequireHttpsAttribute());
}

请注意,这两者只会导致客户端对 GET 请求执行重定向,大多数客户端将忽略 POST 请求的 301/302,因为您不应该重新提交表单。

[RequireHttps] 选项只会为 GET 请求发出重定向,POST 请求将 return 无效操作异常:"Must Use HTTPS".