asp.net c# 从http重定向到https

发布于 2024-10-22 11:42:20 字数 816 浏览 2 评论 0原文

因此,在我的代码中,我想检测我的登录页面是否被称为 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。 没有收到信息错误...同样的事情发生在调试器中没有运行。

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

我做错了什么?我认为这一定是一个完全明显的新秀错误,但我没有看到它。

So in my code I want to detect if my login page is being called http, and redirect it to https.

I know there are non code ways to skin this cat, but for frustrating technical reasosn I'm backed into doing it in code.

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

So I drop this in my Page_Load(...), make sure my debugger uses real IIS, not VS2008s IIS, and hit debug.

Inthe debugger, waltz along, hit
Response.Redirect("https://localhost/StudentPortal3G/AccessControl/AdLogin.aspx"),
hit f5.

Get "Internet Explorere Cannot Display the webpage, url is HTTP, not HTTPS.
Not getting an informative error... same thing happens not running in the debugger.

So what am I missing? it does not appear to be rocket science, I've seen similar code on lots of blogs...

What am I doing wrong? I figure it has to be a totally obvious Rookie mistake, but I'm not seeing it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

蓦然回首 2024-10-29 11:42:20

我也会执行 !Request.IsLocal 来确保我没有进行调试,但如果您使用的是 IIS 的真实实例,并且在调试时应用了证书,则不应进行调试一个问题。

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

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

注意:我已将此更新为与根据 框架文档

当您在页面处理程序中使用此方法来终止对
一个页面并开始另一个页面的新请求,将 endResponse 设置为
false,然后调用 CompleteRequest 方法。如果指定 true
对于 endResponse 参数,此方法调用 End 方法
原始请求,抛出 ThreadAbortException 异常
当它完成时。此异常对 Web 产生不利影响
应用程序性能,这就是为什么传递 false 的原因
建议使用 endResponse 参数。欲了解更多信息,请参阅
结束方法。

I'd do a !Request.IsLocal as well to make sure that I'm not debugging, though if you're using a real instance of IIS with a cert applied when debugging that shouldn't be an issue.

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

Note: This answer assumes an MVC context within a Controller where HttpContext is a property holding the current context. If you're unlucky enough to still be using WebForms or are referencing the context in a degenerate way you will need to use HttpContext.Current.ApplicationInstance.CompleteRequest().

Note: I've updated this to be consistent with the recommended pattern to terminate the request according to the framework documentation.

When you use this method in a page handler to terminate a request for
one page and start a new request for another page, set endResponse to
false and then call the CompleteRequest method. If you specify true
for the endResponse parameter, this method calls the End method for
the original request, which throws a ThreadAbortException exception
when it completes. This exception has a detrimental effect on Web
application performance, which is why passing false for the
endResponse parameter is recommended. For more information, see the
End method.

椒妓 2024-10-29 11:42:20

我通常从我的所有页面继承的基类中的 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);
    }

I usually call the following from the OnPreInit in a base class that all my pages inherit from. Of course, you could just do this in every page...but you wouldn't want to do that now would you?

Note that I've got two properties for each page so that I can specify the SSL requirement for each page (RequiresSSL) while I can also override and redirect check if I want (with IgnoreRequiresSSL, which is helpful for pages like error pages that you rewrite to and don't know whether they'll be encrypted or not), but of course, you can remove these for simple setups.

    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);
    }
对你的占有欲 2024-10-29 11:42:20

我认为以下是最好的全面方法。

三个原因

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

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

 <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>

In my opinion the following is the best all-round approach.

Three reasons

  1. It works for both MVC and Web API as it is done at IIS level.
  2. It does not effect local / debug settings. (permanent redirect can mess you around when debugging non https sites on your pc).
  3. Uses a permanent redirect, so all future requests will automatically go to https

Simply add the following to your <system.webServer> section in your 'Web.config' for your project.

 <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>
岁吢 2024-10-29 11:42:20

您还可以使用新的 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);
}

You can also use the new 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);
}
月棠 2024-10-29 11:42:20

我能够强制执行 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>

One of the ways that I was able to enforce an https redirect is to the following:

In the app pool I have my application running on just port 443 so that there is no possiblity for an unencrypted session to occur (unless encryption scheme is broken through a vulnerability..). I created another application on port 80 with the same IP address which contains just a web.config file with the following code

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

毁我热情 2024-10-29 11:42:20

这是我的解决方案:

// 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 主机名。它进行 301 重定向,这在某些情况下可能是正确的响应。

Here's my solution:

// 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();
}

Where Settings.CanonicalDomain is your HTTPS hostname. It 301 redirects which may be the proper response in some cases.

私野 2024-10-29 11:42:20

我还建议 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);
        }

I would also suggest tvalfonsso's solution, but with a small modification in case you have some url rewriting (RawUrl differs from 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);
        }
三岁铭 2024-10-29 11:42:20

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

我建议使用 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);

disclaimer - I was involved in the development of this project

I would recommend using http://nuget.org/packages/SecurePages/ It gives you the ability to secure specific pages or use Regex to define matches. It will also force all pages not matching the Regex or directly specified back to HTTP.

You can install it via NuGet: Install-Package SecurePages

Docs are here: https://github.com/webadvanced/Secure-Page-manager-for-asp.net#secure-pages

Simple Usage:

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

or

SecurePagesConfiguration.Urls.AddRegex(@"(.*)account", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
唱一曲作罢 2024-10-29 11:42:20

在我的开发环境中,我喜欢有一个单独的发布目录,其中安装了带有自签名证书的 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 检查来使其(稍微)更高效。

On my development environment, I like to have a separate publish directory with IIS installed with a self signed cert, which is different form my code directory without a cert that I debug directly inside of Visual Studio. In this scenario !Request.IsLocal isn't ideal because it doesn't work anywhere on your development environment, even in the IIS directory with the cert. I prefer this:

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

HttpContext.Current.IsDebuggingEnabled is based on the value of compilation debug="true/false" in your web.config. I have it set to true in my code directory, and false in my publish directory when I need to test http and https redirection locally.

I add in the IsPostBack simply to make it (slightly) more efficient by skipping the extra ssl checking when not needed.

浪推晚风 2024-10-29 11:42:20

让 IIS 在不使用重写的情况下执行此操作的简单方法:

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

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

A simple way to get IIS to do it without using Rewrite:

  1. IIS SSL Settings: Set SSL Required.
  2. IIS Error Pages: Change the IIS 403 Error code to redirect to the https url.

You can also add from the web.config in the HttpErrors section.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文