【问题标题】:asp.net c# redirecting from http to httpsasp.net c#从http重定向到https
【发布时间】:2011-07-15 09:29:27
【问题描述】:

所以在我的代码中,我想检测我的登录页面是否被称为 http,并将其重定向到 https。

我知道有非代码方法可以给这只猫剥皮,但出于令人沮丧的技术原因,我支持在代码中这样做。

            if (!Request.IsSecureConnection)
            {
                string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
                Response.Redirect(redirectUrl);
            }

所以我把它放在我的Page_Load(...) 中,确保我的调试器使用真正的 IIS,而不是 VS2008s IIS,然后点击调试。

在调试器中,跳华尔兹,点击 Response.Redirect("https://localhost/StudentPortal3G/AccessControl/AdLogin.aspx"), 按 f5。

得到“Internet Explorer 无法显示网页,url 是 HTTP,不是 HTTPS。 没有得到信息性错误...同样的事情没有在调试器中运行。

那么我错过了什么?它似乎不是火箭科学,我在很多博客上都看到过类似的代码......

我做错了什么?我认为这一定是一个非常明显的 Rookie 错误,但我没有看到。

【问题讨论】:

  • 在 IE 中关闭“显示友好的错误消息”,看看它是什么意思。如果“友好”(我用这个词很松散)错误消息被打开并且 IE 得到一个非 200 状态代码并且信息小于 512 字节,它就会打开盲注。
  • @Chris - 我关闭了该设置,但仍然出现相同的错误。任何想法如何获得信息错误?
  • @StackOverflowException - 我不确定我是否理解这个答案,你的意思是使用常量“Uri.UriSchemeHttps”而不是“http”和“https”?我两种方式都试过了。 .

标签: asp.net http https


【解决方案1】:

我也会发送!Request.IsLocal 以确保我没有在调试,但如果您使用的是真实的 IIS 实例,并且在调试时应用了证书,这应该不是问题。

if (!Request.IsLocal && !Request.IsSecureConnection)
{
    string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
    Response.Redirect(redirectUrl, false);
    HttpContext.ApplicationInstance.CompleteRequest();
}

注意:此答案假定 Controller 中有一个 MVC 上下文,其中 HttpContext 是保存当前上下文的属性。如果您很不幸仍然在使用 WebForms 或以退化的方式引用上下文,您将需要使用 HttpContext.Current.ApplicationInstance.CompleteRequest()

注意:我已将其更新为与推荐的模式一致,以根据 framework documentation 终止请求。

当您在页面处理程序中使用此方法来终止对 一个页面并开始对另一个页面的新请求,将 endResponse 设置为 false 然后调用 CompleteRequest 方法。如果您指定 true 对于 endResponse 参数,此方法调用 End 方法 引发 ThreadAbortException 异常的原始请求 当它完成时。此异常对 Web 有不利影响 应用程序性能,这就是为什么为 推荐使用 endResponse 参数。有关详细信息,请参阅 结束方法。

【讨论】:

  • 该重定向只有一个问题:会话变量可能会丢失。
  • @The_Ghost 怎么会这样?我不确定你在说什么。
  • @The_Ghost - 似乎只有当您尝试在响应终止后执行的代码中设置那些。不过,由于性能问题,Microsoft 确实建议使用 false,我会更新。
  • 尽管这篇文章很旧,但我还是通过将 HttpContext.ApplicationInstance.CompleteRequest(); 替换为 HttpContext.Current.ApplicationInstance.CompleteRequest(); 来完成这项工作。
  • 阅读Request.Url.ToString()的一个小问题是,如果查询字符串包含任何 URL 编码参数,它将解码它们并搞砸重定向。例如。 mypage.aspx?q=a%3D1%26b%3D2%26c%3D3 将被重定向为 mypage.aspx?q=a=1&b=2&c=3
【解决方案2】:

我通常从我所有页面继承的基类中的 OnPreInit 调用以下内容。当然,您可以在每个页面中都这样做……但您现在不想这样做吧?

请注意,我为每个页面设置了两个属性,因此我可以为每个页面指定 SSL 要求 (RequiresSSL),同时我还可以根据需要覆盖和重定向检查(使用 IgnoreRequiresSSL,这对于错误之类的页面很有帮助您重写的页面并且不知道它们是否会被加密),但当然,您可以删除这些以进行简单的设置。

    protected override void OnPreInit(EventArgs e)
    {
        base.OnPreInit(e);

        if (!IsPostBack)
            RedirectAccordingToRequiresSSL();

        ...
    }

    /// <summary>
    /// Redirect if necessary to ssl or non-ssl enabled URL dependant on RequiresSSL property setting.
    /// </summary>
    private void RedirectAccordingToRequiresSSL()
    {
        if (IgnoreRequiresSSL) return;

        if (RequiresSSL)
        {
            if (!Request.IsSecureConnection) // Need to redirect to https
                RedirectAccordingToRequiresSSL(Uri.UriSchemeHttps);
        }
        else if (Request.IsSecureConnection)
        {
            RedirectAccordingToRequiresSSL(Uri.UriSchemeHttp);
        }

        // Otherwise don't need to do any redirecting as already using the correct scheme
    }

    /// <summary>
    /// Redirect as requested to specified scheme
    /// </summary>
    /// <param name="scheme"></param>
    private void RedirectAccordingToRequiresSSL(string scheme)
    {
        var url = scheme + Uri.SchemeDelimiter + Request.Url.Authority + Request.Url.PathAndQuery;
        Response.Redirect(url, false);
    }

【讨论】:

  • 这显然是一个更好的解决方案,我在搜索时阅读了您的文章,但是直到我实施的“丑陋”解决方案起作用,这也不会,对吗?因为最后 ResponseRedirect 从 http 到 https “手动”,我正确吗?
  • 是的。您的核心问题是没有正确安装证书并将其分配给站点 - 如果您需要帮助,请询问。
  • +1 表示乐于助人,并有更好的通用解决方案,即使我选择了上面标记的答案。
  • 谢谢,我在几分钟内就在一个复杂的网站上实施了您干净且无痛的解决方案;而昨天我挣扎了几个小时,但没有成功尝试在 web.config 中使用 URL 重写规则实现等效。您的解决方案适用于 aspx 登录控件和成员资格,包括查询字符串中的重定向。我无法让一组重写规则起作用——也许这是我缺乏理解的部分原因,但支持文档可能会更有帮助。此外,您对我的解决方案比投票更多的解决方案更有帮助,因为您的解决方案是双向的:httpshttp.
【解决方案3】:

免责声明 - 我参与了这个项目的开发

我建议使用http://nuget.org/packages/SecurePages/ 它使您能够保护特定页面或使用正则表达式来定义匹配项。它还将强制所有不匹配正则表达式或直接指定的页面返回 HTTP。

你可以通过 NuGet 安装它:Install-Package SecurePages

文档在这里:https://github.com/webadvanced/Secure-Page-manager-for-asp.net#secure-pages

简单用法:

SecurePagesConfiguration.Urls.AddUrl("/cart");

SecurePagesConfiguration.Urls.AddRegex(@"(.*)account", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);

【讨论】:

  • 感谢您发布您的答案!请务必仔细阅读FAQ on Self-Promotion。另请注意,每次链接到自己的网站/产品时,都要求发布免责声明。
  • 酷,有人应该回去告诉所有曾经在 S.O 上自我宣传过他们的工作的人为了公平起见添加免责声明......
【解决方案4】:

这是我的解决方案:

// Force HTTPS connection
if (!Request.IsSecureConnection)
{
    var uri = new Uri(Request.Url.ToString());
    var redirectUrl = Settings.CanonicalDomain + uri.PathAndQuery;
    Response.Status = "301 Moved Permanently";
    Response.AddHeader("Location", redirectUrl);
    Response.End();
}

Settings.CanonicalDomain 是您的 HTTPS 主机名。 It 301 重定向在某些情况下可能是正确的响应。

【讨论】:

    【解决方案5】:

    在我的开发环境中,我喜欢有一个单独的发布目录,其中安装了带有自签名证书的 IIS,这与我没有直接在 Visual Studio 中调试的证书的代码目录不同。在这种情况下,!Request.IsLocal 并不理想,因为它在您的开发环境中的任何地方都不起作用,即使在带有证书的 IIS 目录中也是如此。我更喜欢这个:

    if (!IsPostBack && !HttpContext.Current.IsDebuggingEnabled) 
    {
        // do http->https and https->http redirection here
    }
    

    HttpContext.Current.IsDebuggingEnabled 基于 web.config 中编译 debug="true/false" 的值。当我需要在本地测试 http 和 https 重定向时,我在代码目录中将其设置为 true,在发布目录中设置为 false。

    我添加了IsPostBack 只是为了通过在不需要时跳过额外的 ssl 检查来(稍微)提高效率。

    【讨论】:

      【解决方案6】:

      我也会建议 tvalfonsso 的解决方案,但要进行一些小修改,以防你有一些 url 重写(RawUrl 与 Url 不同)

          if (SPPage == SPPages.StartAutotrading && !Request.IsLocal && !Request.IsSecureConnection)
              {
                  string redirectUrl = (Request.Url.ToString().Replace(Request.Url.PathAndQuery.ToString(), "") + Request.RawUrl).Replace("http:", "https:");
                  Response.Redirect(redirectUrl);
              }
      

      【讨论】:

        【解决方案7】:

        您也可以使用新的 UriBuilder:

        Dim context As HttpContext = HttpContext.Current
        If Not context.Request.IsSecureConnection Then
            Dim secureUrl As New UriBuilder(context.Request.Url)
            secureUrl.Scheme = "https"
            secureUrl.Port = 443
            context.Response.Redirect(secureUrl.ToString, False)
            Return
        End If
        

        C#

        HttpContext context = HttpContext.Current;
        if (!context.Request.IsSecureConnection)
        {
            UriBuilder secureUrl = new UriBuilder(context.Request.Url);
            secureUrl.Scheme = "https";
            secureUrl.Port = 443;
            context.Response.Redirect(secureUrl.ToString(), false);
        }
        

        【讨论】:

        • 这样更好,因为您可以使用默认 443 以外的端口。
        【解决方案8】:

        我能够强制执行 https 重定向的方法之一是:

        在应用程序池中,我的应用程序仅在端口 443 上运行,因此不可能发生未加密的会话(除非加密方案被漏洞破坏......)。我在端口 80 上创建了另一个具有相同 IP 地址的应用程序,其中仅包含一个 web.config 文件,其中包含以下代码

        <?xml version="1.0" encoding="UTF-8"?>
        <configuration>
        <system.webServer>
            <httpRedirect enabled="true" destination="https://yourWebsiteURL.com" />
        </system.webServer>
        

        【讨论】:

        【解决方案9】:

        在我看来,以下是最好的全方位方法。

        三个原因

        1. 它适用于 MVCWeb API,因为它是在 IIS 级别完成的。
        2. 它不影响本地/调试设置。 (在您的 PC 上调试非 https 站点时,永久重定向可能会搞砸您)。
        3. 使用永久重定向,因此所有未来的请求将自动转到https

        只需将以下内容添加到项目的“Web.config”中的 &lt;system.webServer&gt; 部分即可。

         <system.webServer>
         ....
        
         <rewrite>
          <rules>
            <rule name="HTTP to HTTPS redirect" stopProcessing="true">
              <match url="(.*)" />
              <conditions>
                <add input="{HTTP_HOST}" pattern="localhost" negate="true" />
                <add input="{HTTPS}" pattern="off" ignoreCase="true" />
              </conditions>
              <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
            </rule>
          </rules>
          <outboundRules>
            <rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
              <match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
              <conditions>
                <add input="{HTTPS}" pattern="on" ignoreCase="true" />
              </conditions>
              <action type="Rewrite" value="max-age=31536000" />
            </rule>
          </outboundRules>
        </rewrite>
        </system.webServer>
        

        【讨论】:

        • 这个答案很好,除了&lt;rewrite&gt;标签进入&lt;system.webServer&gt;
        • @FranzWimmer 它应该去哪里?如果&lt;system.webserver&gt;中没有
        • 注意:您需要安装 Rewrite 模块才能使其工作,否则您只会收到 500 错误 - 请参阅 docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/…
        【解决方案10】:

        让 IIS 不使用 Rewrite 的简单方法:

        1. IIS SSL 设置:设置 SSL 必需。
        2. IIS 错误页面:更改 IIS 403 错误代码以重定向到 https url。

        您也可以从 web.config 的 HttpErrors 部分添加。

        【讨论】:

          猜你喜欢
          • 2011-09-28
          • 1970-01-01
          • 2017-09-05
          • 2019-09-10
          • 2017-10-06
          • 2017-11-04
          • 2016-01-17
          • 2017-07-18
          • 2018-04-09
          相关资源
          最近更新 更多