在IIS 7中启用HTTP严格传输安全性(HSTS)


75

在IIS 7 Web服务器上打开HTTP Strict Transport Security的最佳方法是什么?

我可以仅通过GUI并添加正确的HTTP响应标头,还是应该使用appcmd?


1
这在很大程度上取决于您如何生成IIS服务的内容(例如,您可以在应用程序中的PHP或ASP.NET页面中设置标头)。您能告诉我们更多有关您的用例的信息吗?
voretaq7

Answers:


18

IIS可以向响应中添加自定义标头。这似乎是最简单的方法。

根据IIS.net上的文档,您可以通过IIS管理器添加以下标头:

  • 在“连接”窗格中,转到要为其设置自定义HTTP标头的站点,应用程序或目录。
  • 在“主页”窗格中,双击“ HTTP响应头”。
  • 在“ HTTP响应标题”窗格中,单击“操作”窗格中的“添加...”。
  • 在“添加自定义HTTP响应标头”对话框中,设置自定义标头的名称和值,然后单击“确定”。

5
您也可以在Web.config中执行此操作。我将这些细节作为新答案发布,因为如果没有注释中没有的源代码格式,它们将很难阅读。
Owen Blacker

3
根据HTTP Strict Transport Security IIS Module的制造商的说法,仅添加自定义标头不符合规范草案(RFC 6797)。您实际上需要安装此IIS模块。
克里斯

@Chris他们错了。与规范无关-它们在那里是绝对正确的-但关于除了模块之外没有“简单”的合规性的事实:只需创建2个站点,一个站点用于SSL(带有标头),另一个站点用于非SSL(没有标题)。当然,该模块稍微优雅一点,但这不是必需的(如果您的站点仅是https且您不提供简单的HTTP响应,则完全不需要保证)。
voretaq7 2014年

1
@Chris您应该添加引用该模块的答案-免费投票!(我不知道它的存在,而且对于很多人来说,这可能比自定义标头的东西更容易/更好)
voretaq7 2014年

112

这使我们既可以处理HTTP重定向,又可以通过单个IIS站点将Strict-Transport-Security标头添加到HTTPS响应(必须安装URL重写模块):

<?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}{REQUEST_URI}"
                        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; includeSubDomains; preload" />
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

7
谢谢,这是最好的答案!与程序化方法不同,也将标头添加到静态HTML文件中。并且不添加到HTTP,因此符合标准。
Jeow Li Huan 2014年

4
@Mathemats您是否在IIS中安装了URL Rewrite?
道格·威尔逊

3
不,经过更多研究,我发现重写标记由扩展名(d'oh)提供。我能找到的所有答案都没有将扩展名作为依赖项提及,也许您可​​以在答案中添加一行以表示您需要它。
Mathemats

2
hstspreload.org希望用户添加`; includeSubDomains; 在最大年龄值之后预载。选项。全线将是:<action type="Rewrite" value="max-age=31536000 ;includeSubDomains; preload" />获得一个上hstspreload.org
JP Hellemons

2
具有模式(。*)的捕获组R:1匹配整个URL,协议和所有URL,尝试连接{HTTP_HOST} / {R:1}意味着您可以得到https://somedomain.com/https://somedomain.com/relatedpath,结果是删除了路径。
AaronLS

38

为了补充voretaq7的答案,您还可以使用Web.config文件来完成此操作(注意:仅用于SSL站点,因为它将添加HTTP和HTTPS响应的标头,这违反了RFC 6797规范,请参阅下面的说明)-如下添加一个代码块:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Strict-Transport-Security" value="max-age=31536000"/>
        </customHeaders>
    </httpProtocol>
</system.webServer>

显然,您system.webServer的Web.config中可能已经有一个块,因此请添加该块。我们更喜欢在Web.config中而不是在GUI中处理内容,因为这意味着可以将配置更改提交到我们的Git存储库。

Greg Askew所述,如果您想处理HTTP到SSL的重定向,则可能会发现在IIS中使用单独的网站更容易做到这一点。这就是我们处理某些客户端站点要求SSL的方式。该站点仅在Web.config中包含HTTP重定向和一些信息泄露修复程序:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <httpRuntime requestValidationMode="2.0" enableVersionHeader="false" />
  </system.web>
  <system.webServer>
    <httpRedirect enabled="true" destination="https://www.domain.co.uk/"
      httpResponseStatus="Permanent" />
    <httpProtocol>
      <customHeaders>
        <remove name="X-Powered-By" />
      </customHeaders>
    </httpProtocol>
    <rewrite>
      <outboundRules>
        <rule name="Remove RESPONSE_Server">
          <match serverVariable="RESPONSE_Server" pattern=".+" />
          <action type="Rewrite" value="" />
        </rule>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>

这是我们的首选解决方案,其原因有两个-我们可以轻松地分别记录重定向的流量(因为它位于不同的IIS日志中),它在Global.asax.cs中不涉及更多代码(我们没有任何代码)在那里,这对于Umbraco站点来说更为方便),而且重要的是,这意味着所有配置仍保留在我们的GIT存储库中。

编辑补充:要明确,为了符合RFC 6797中,Strict-Transport-Security自定义标题不得被添加到通过未加密的HTTP的请求。为了符合RFC6797,您必须在IIS中有两个站点,正如我在第一个代码块之后所述。正如克里斯指出,RFC 6797包括:

一个HSTS主机必须不包括在传送非安全传输的HTTP响应的STS头字段。

因此,发送Strict-Transport-Security客户标头以响应非SSL请求将不符合规范。


1
要添加到Owen Blacker响应中,对于IIS,我使用URLScan 3.1,并通过设置RemoveServerHeader = 1使它从响应中全局删除SERVER,其余设置必须位于每个站点web.config文件中。我更喜欢这样,而不是消隐价值。
KeyOfJ

URLScan是一种非常常见的解决方案,我建议比我建议的解决方案更好。但这并不总是最方便的解决方案:o)
Owen Blacker 2014年

重要的是要注意,将其添加到启用了HTTPS和HTTP(以便可以重定向)的网站上会使网站崩溃!即使使用CustomErrors Mode =“ Off”,您也将获得无信息的500,日志中没有错误。
克里斯·莫斯奇尼

@ChrisMoschini我应该更清楚地知道第一行Web.config行应该用于仅SSL站点。
Owen Blacker'3

1
@Lenne Scott Hanselman对使用HTTP时为什么STS不属于标题的问题进行了更为详尽的描述。在这里
David Yates

8

我将使用您引用的Wikipedia链接中的示例,并在global.asax中为该网站执行活动。这样可以将请求重定向到https url,然后将标头插入响应中。

这是因为如果HSTS标头不在https响应中,则必须将其忽略。

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

3

这似乎是一种相当安全的方法。将此代码添加到Global.asax中-在Asp.net请求生命周期中,首先触发Application_BeginRequest事件:http : //msdn.microsoft.com/zh-cn/library/system.web.httpapplication.beginrequest( v= vs。 110).aspx

根据规范,http请求不得以标头响应-因此此代码仅将其添加到https请求中。最大寿命以秒为单位,通常最好在此处输入较大的值(IE 31536000表示该站点仅在接下来的365天运行SSL)

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

2

使用Doug Wilson提供的示例,我创建了以下两个PowerShell函数,以添加URL重写规则以重定向到HTTPS和添加HSTS标头。

这些已在Windows 2012和Windows 2012 R2上进行了测试。

您需要做的就是提供网站名称。如果您不喜欢默认值,则可以选择为规则指定其他名称。

需要注意的一件事是,根据我的测试,需要将服务器变量添加到允许列表中,然后才能放入响应头中。函数为您完成此操作。

编辑:请参阅有关HTTP标头的网址重写的参考,网址为:http : //www.iis.net/learn/extensions/url-rewrite-module/setting-http-request-headers-and-iis-server-variables

Function Add-HTTPSRedirectRewriteRule()
{
    <#
        .SYNOPSIS
        This function is used to create a URL Rewrite Rule that redirects HTTP requests to HTTPS using a 301
        RuleName is optional and will default to "Redirect to HTTPS"

        .SYNTAX
        Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com"

        .EXAMPLES
        Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com"

        Add-HTTPSRedirectRewriteRule -WebsiteName "www.mywebsite.com" -RuleName "my rule name"

    #>


    [cmdletbinding(positionalbinding=$false)]
    Param
    (
        [parameter(mandatory=$true)][String] [ValidateNotNullOrEmpty()] $WebsiteName,
        [parameter(mandatory=$false)][String] $RuleName="Redirect to HTTPS"
    )

        Write-Verbose -Message "Creating the Url Rewrite rule ""$RuleName"" in website ""$WebsiteName"""
        Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/rules" -name "." -AtElement @{name="$RuleName"}  -ErrorAction SilentlyContinue
        Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules" -name "." -value @{name="$RuleName";stopProcessing='True'}
        Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/match" -name "url" -value "(.*)"
        Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/conditions" -name "." -value @{input='{HTTPS}';pattern='off'}
        Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "type" -value "Redirect"
        Set-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/rules/rule[@name='$RuleName']/action" -name "url" -value "https://{HTTP_HOST}/{R:1}"
}

Function Add-HSTSHeaderRewriteRule()
{
    <#
        .SYNOPSIS
        This function is used to create a URL Rewrite Rule that sets an HTTP Response Header for Strict-Transport-Security
        when the protocol requested is HTTPS

        RuleName is optional and will default to "Add Strict-Transport-Security header when request is HTTPS"

        .SYNTAX
        Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com"

        .EXAMPLES
        Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com"

        Add-HSTSHeaderRewriteRule -WebsiteName "www.mywebsite.com" -RuleName "my rule name"

    #>

    [cmdletbinding(positionalbinding=$false)]
    Param
    (
        [parameter(mandatory=$true)][String] [ValidateNotNullOrEmpty()] $WebsiteName,
        [parameter(mandatory=$false)][String]$RuleName="Add Strict-Transport-Security header when request is HTTPS"
    )

    $serverVariable = "RESPONSE_Strict_Transport_Security"

    Write-Verbose -Message "Creating the HSTS Header rule ""$RuleName"" in website ""$WebsiteName"""

    Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName" -filter "system.webServer/rewrite/allowedServerVariables" -name "." -AtElement @{name="$serverVariable"} -ErrorAction SilentlyContinue
    Add-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -location "$WebsiteName"  -filter "system.webServer/rewrite/allowedServerVariables" -name "." -value @{name="$serverVariable"}

    Remove-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -name "." -filter "system.webServer/rewrite/outboundRules" -AtElement @{name="$RuleName"} -ErrorAction SilentlyContinue

    Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules" -name "." -value @{name="$RuleName"}
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/match" -name "serverVariable" -value $serverVariable
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/match" -name "pattern" -value ".*"
    Add-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/conditions" -name "." -value @{input='{HTTPS}';pattern='on'}
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/action" -name "type" -value "Rewrite"
    Set-WebConfigurationProperty -pspath "MACHINE/WEBROOT/APPHOST" -location "$WebsiteName" -filter "system.webServer/rewrite/outboundRules/rule[@name='$RuleName']/action" -name "value" -value "max-age=31536000"

}

1

根据HTTP Strict Transport Security IIS模块的制造商的说法,仅添加自定义标头不符合规范草案(RFC 6797)。

实际上,您实际上需要安装此IIS模块才能在IIS 7上打开HSTS。

2014年10月26日更新:多亏了以下评论者,我再次阅读了模块页面,尤其是通过添加自定义标头来证明该模块合理使用的部分。

HSTS主机不得在通过非安全传输传递的HTTP响应中不包含STS头字段。

如果确保仅在HTTPS中添加标头,而不在HTTP中添加标头,则不需要此模块,可以使用Doug Wilson的答案。不要使用Owen Blacker的答案,因为它没有https条件。


1
那么,仅将标头发送到HTTPS请求的其他一些答案也可以解决此问题吗?还是您的模块做了其他解决方案没有做的其他事情?
slolife 2014年

@slolife我更新了答案。您可以在Doug Wilson的答案中使用该代码。您不需要此模块。我现在看到在接受的答案的注释中也对此进行了讨论。我不知道该模块所做的其他事情与其他解决方案没有什么不同。但是我也没有对源代码进行详尽的检查。
克里斯(Chris)

我应该更加清楚,第一个Web.config应该在仅SSL的站点中实现。我将编辑我的答案以澄清这一点。
Owen Blacker'3

1

这可以通过在Web.Config中添加以下代码块来完成:

<system.webServer>
    <httpProtocol>
      <customHeaders>
        <add name ="CustomName" value="MyCustomValue"/>
      </customHeaders>
    </httpProtocol>
</system.webServer>

我们必须在IIS上进行配置,该IIS能够自定义标头以进行响应:

  • 转到“ Internet信息服务(IIS)管理器”。
  • 配置添加到服务器响应中的响应头。
  • 现在添加您的自定义标头名称和自定义值(自定义标头名称和值应与Web.Config中的相同)。你可以在博客上找到

0

补充一下,我在评论中看到2个人在执行此操作时谈论500个错误。我有这个

如果您在IIS中收到500错误,则可能是因为您同时在顶级,站点级别和继承级别都添加了该规则。

例如

Default Web Site <- here
  Some Web Site <- here

IIS /浏览器似乎没有为您提供执行此操作的任何信息,无论您的错误处理设置如何

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.