大约6个月前,我推出了一个网站,每个请求都需要通过https。当时我能找到的确保每个页面请求都是通过https的唯一方法是在页面加载事件中检查它。如果请求不是通过http,我会response.redirect("https://example.com")

有没有更好的方法,比如web。config中的一些设置?


当前回答

在IIS10 (Windows 10和Server 2016)中,从1709版本开始,有一个新的、更简单的选项可以为网站启用HSTS。

微软在这里描述了新方法的优点,并提供了许多不同的示例,说明如何通过编程或直接编辑ApplicationHost实现更改。配置文件(类似web。配置,但操作在IIS级别,而不是个别站点级别)。ApplicationHost。config可以在c:\ windows \ system32 \inetsrv\config目录下找到。

我在这里概述了避免链接失效的两个示例方法。

方法1 -编辑ApplicationHost。配置文件 在<site>标签之间,添加这一行:

<hsts enabled="true" max-age="31536000" includeSubDomains="true" redirectHttpToHttps="true" />

方法2—命令行: 从升高的命令提示符(即在CMD上用鼠标右键并以管理员身份运行)执行以下命令。请记住在IIS管理器中显示的站点名称与Contoso交换。

c:
cd C:\WINDOWS\system32\inetsrv\
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.enabled:True" /commit:apphost
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.max-age:31536000" /commit:apphost
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.includeSubDomains:True" /commit:apphost
appcmd.exe set config -section:system.applicationHost/sites "/[name='Contoso'].hsts.redirectHttpToHttps:True" /commit:apphost

如果您处于访问受限的托管环境中,那么微软在文章中提供的其他方法可能是更好的选择。

请记住,IIS10版本1709现在可以在Windows 10上使用,但对于Windows Server 2016,它在不同的发布轨道上,并且不会作为补丁或服务包发布。点击这里了解1709年的详细信息。

其他回答

请使用HSTS (HTTP严格传输安全)

从http://www.hanselman.com/blog/HowToEnableHTTPStrictTransportSecurityHSTSInIIS7.aspx

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                        <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>
</configuration>

原答案(2015年12月4日取代)

基本上

protected void Application_BeginRequest(Object sender, EventArgs e)
{
   if (HttpContext.Current.Request.IsSecureConnection.Equals(false) && HttpContext.Current.Request.IsLocal.Equals(false))
   {
    Response.Redirect("https://" + Request.ServerVariables["HTTP_HOST"]
+   HttpContext.Current.Request.RawUrl);
   }
}

它会被放到global。asax。cs(或global。asax。vb)

我不知道如何在web.config中指定它

您还可以通过向浏览器返回“Strict-Transport-Security”报头来使用HSTS。浏览器必须支持这一点(目前主要是Chrome和Firefox支持),但这意味着一旦设置好,浏览器将不会通过HTTP向站点发出请求,而是在发出请求之前将它们转换为HTTPS请求。尝试结合从HTTP重定向:

protected void Application_BeginRequest(Object sender, EventArgs e)
{
  switch (Request.Url.Scheme)
  {
    case "https":
      Response.AddHeader("Strict-Transport-Security", "max-age=300");
      break;
    case "http":
      var path = "https://" + Request.Url.Host + Request.Url.PathAndQuery;
      Response.Status = "301 Moved Permanently";
      Response.AddHeader("Location", path);
      break;
  }
}

不了解HSTS的浏览器将忽略头文件,但仍然会被switch语句捕获并发送到HTTPS。

对于上面的@Joe,“这是给我一个重定向循环。在我添加代码之前,它工作得很好。有什么建议吗?——乔11月8日11月4点13分

这种情况也发生在我身上,我认为发生的情况是有一个负载均衡器在Web服务器前终止SSL请求。因此,我的Web站点总是认为请求是“http”,即使原始浏览器要求它是“https”。

I admit this is a bit hacky, but what worked for me was to implement a "JustRedirected" property that I could leverage to figure out the person was already redirected once. So, I test for specific conditions that warrant the redirect and, if they are met, I set this property (value stored in session) prior to the redirection. Even if the http/https conditions for redirection are met the second time, I bypass the redirection logic and reset the "JustRedirected" session value to false. You'll need your own conditional test logic, but here's a simple implementation of the property:

    public bool JustRedirected
    {
        get
        {
            if (Session[RosadaConst.JUSTREDIRECTED] == null)
                return false;

            return (bool)Session[RosadaConst.JUSTREDIRECTED];
        }
        set
        {
            Session[RosadaConst.JUSTREDIRECTED] = value;
        }
    }

我花了一些时间寻找有意义的最佳实践,发现下面的方法非常适合我。我希望这能帮你节省时间。

使用配置文件(例如asp.net网站) https://blogs.msdn.microsoft.com/kaushal/2013/05/22/http-to-https-redirects-on-iis-7-x-and-higher/

或者在你自己的服务器上 https://www.sslshopper.com/iis7-redirect-http-to-https.html

(简答) 下面的代码放在里面

<system.webServer> 
 <rewrite>
     <rules>
       <rule name="HTTP/S to HTTPS Redirect" enabled="true" 
           stopProcessing="true">
       <match url="(.*)" />
        <conditions logicalGrouping="MatchAny">
        <add input="{SERVER_PORT_SECURE}" pattern="^0$" />
       </conditions>
       <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" 
        redirectType="Permanent" />
        </rule>
       </rules>
 </rewrite>

你需要做的是:

1)在web中添加一个键。配置,取决于生产或阶段服务器如下所示

<add key="HttpsServer" value="stage"/>
             or
<add key="HttpsServer" value="prod"/>

2)在Global内部。Asax文件添加如下方法。

void Application_BeginRequest(Object sender, EventArgs e)
{
    //if (ConfigurationManager.AppSettings["HttpsServer"].ToString() == "prod")
    if (ConfigurationManager.AppSettings["HttpsServer"].ToString() == "stage")
    {
        if (!HttpContext.Current.Request.IsSecureConnection)
        {
            if (!Request.Url.GetLeftPart(UriPartial.Authority).Contains("www"))
            {
                HttpContext.Current.Response.Redirect(
                    Request.Url.GetLeftPart(UriPartial.Authority).Replace("http://", "https://www."), true);
            }
            else
            {
                HttpContext.Current.Response.Redirect(
                    Request.Url.GetLeftPart(UriPartial.Authority).Replace("http://", "https://"), true);
            }
        }
    }
}