关于c#:asp.net中对整个网站强制使用https的最佳方法?

关于c#:asp.net中对整个网站强制使用https的最佳方法?

Best way in asp.net to force https for an entire site?

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

有没有更好的方法-理想情况下是web.config中的某些设置?


请使用HSTS

来自http://www.hanselman.com/blog/HowToEnableHTTPStrictTransportSecurityHSTSInIIS7.aspx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                    <match url="(.*)" />
                    <conditions>
                       
                    </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>
                       
                    </conditions>
                   
                </rule>
            </outboundRules>
        </rewrite>
    </system.webServer>
</configuration>

原始答案(于2015年12月4日替换为上述内容)

基本上

1
2
3
4
5
6
7
8
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一起尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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。


IIS7模块将允许您重定向。

1
2
3
4
5
6
7
8
9
10
11
    <rewrite>
        <rules>
            <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
                <match url="(.*)"/>
                <conditions>
                   
                </conditions>
               
            </rule>
        </rules>
    </rewrite>

对于那些使用ASP.NET MVC的用户。您可以使用以下两种方法在整个站点上通过HTTPS强制SSL / TLS:

艰难的道路

1-将RequireHttpsAttribute添加到全局过滤器:

1
GlobalFilters.Filters.Add(new RequireHttpsAttribute());

2-强制防伪令牌使用SSL / TLS:

1
AntiForgeryConfig.RequireSsl = true;

3-默认情况下,通过更改Web.config文件,要求Cookies要求HTTPS:

1
2
3
<system.web>
    <httpCookies httpOnlyCookies="true" requireSSL="true" />
</system.web>

4-使用NWebSec.Owin NuGet程序包并添加以下代码行以启用整个站点的严格传输安全性。不要忘记在下面添加Preload指令并将您的站点提交到HSTS Preload站点。这里和这里有更多信息。请注意,如果您不使用OWIN,则可以在NWebSec站点上阅读Web.config方法。

1
2
// app is your OWIN IAppBuilder app in Startup.cs
app.UseHsts(options => options.MaxAge(days: 30).Preload());

5-使用NWebSec.Owin NuGet包并添加以下代码行以在整个站点上启用公钥固定(HPKP)。这里和这里有更多信息。

1
2
3
4
5
6
// app is your OWIN IAppBuilder app in Startup.cs
app.UseHpkp(options => options
    .Sha256Pins(
       "Base64 encoded SHA-256 hash of your first certificate e.g. cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=",
       "Base64 encoded SHA-256 hash of your second backup certificate e.g. M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=")
    .MaxAge(days: 30));

6-在使用的任何URL中包括https方案。在某些浏览器中模仿该方案时,内容安全策略(CSP)HTTP标头和子资源完整性(SRI)不能很好地发挥作用。最好对HTTPS明确。例如

1
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.4/bootstrap.min.js">

简单的方法

使用ASP.NET MVC Boilerplate Visual Studio项目模板来生成一个包含所有这些内容以及更多内容的项目。您还可以在GitHub上查看代码。


如果由于某种原因您无法在IIS中进行设置,我将制作一个HTTP模块为您执行重定向:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Web;

namespace HttpsOnly
{
    /// <summary>
    /// Redirects the Request to HTTPS if it comes in on an insecure channel.
    /// </summary>
    public class HttpsOnlyModule : IHttpModule
    {
        public void Init(HttpApplication app)
        {
            // Note we cannot trust IsSecureConnection when
            // in a webfarm, because usually only the load balancer
            // will come in on a secure port the request will be then
            // internally redirected to local machine on a specified port.

            // Move this to a config file, if your behind a farm,
            // set this to the local port used internally.
            int specialPort = 443;

            if (!app.Context.Request.IsSecureConnection
               || app.Context.Request.Url.Port != specialPort)
            {
               app.Context.Response.Redirect("https://"
                  + app.Context.Request.ServerVariables["HTTP_HOST"]
                  + app.Context.Request.RawUrl);    
            }
        }

        public void Dispose()
        {
            // Needed for IHttpModule
        }
    }
}

然后只需将其编译为DLL,将其添加为对您的项目的引用,并将其放置在web.config中:

1
2
3
 <httpModules>
     
 </httpModules>

您需要做的是:

1)根据生产或阶段服务器(如下所示)在web.config中添加一个密钥

1
             or

2)在您的Global.asax文件中添加以下方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
            }
        }
    }
}


如果无法在您的站点中配置SSL支持(即应该能够打开/关闭https),则可以在要保护的任何控制器/控制器操作上使用[RequireHttps]属性。


这是基于@Troy Hunt的完整答案。将此函数添加到Global.asax.cs中的WebApplication类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    protected void Application_BeginRequest(Object sender, EventArgs e)
    {
        // Allow https pages in debugging
        if (Request.IsLocal)
        {
            if (Request.Url.Scheme =="http")
            {
                int localSslPort = 44362; // Your local IIS port for HTTPS

                var path ="https://" + Request.Url.Host +":" + localSslPort + Request.Url.PathAndQuery;

                Response.Status ="301 Moved Permanently";
                Response.AddHeader("Location", path);
            }
        }
        else
        {
            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;
            }
        }
    }

(要在本地版本上启用SSL,请在项目的"属性"扩展坞中启用它)


我将投入两分钱。如果您可以访问IIS服务器端,则可以使用协议绑定强制HTTPS。例如,您有一个名为Blah的网站。在IIS中,您将设置两个站点:Blah和Blah(重定向)。对于Blah,仅配置HTTPS绑定(如果需要,还配置FTP,请确保也通过安全连接强制它)。对于Blah(重定向),仅配置HTTP绑定。最后,在Blah的HTTP重定向部分(重定向)中,确保将301重定向设置为https://blah.com,并启用了确切的目的地。确保IIS中的每个站点都指向它自己的根文件夹,否则Web.config将被搞砸。还要确保在HTTPSed站点上配置了HSTS,以便浏览器的后续请求始终被强制为HTTPS,并且不会发生重定向。


对于上面的@Joe,"这给了我一个重定向循环。在添加代码之前,它工作正常。有什么建议吗?– 2011年11月8日,乔4:13"

我也正在发生这种情况,我认为正在发生的是在Web服务器前面有一个负载均衡器终止SSL请求。因此,即使原始浏览器将其请求为" https",我的网站也始终认为该请求为" http"。

我承认这有点棘手,但是对我有用的是实现一个" JustRedirected"属性,我可以利用该属性确定该人已经被重定向了一次。因此,我测试了保证重定向的特定条件,如果满足这些条件,则会在重定向之前设置此属性(存储在会话中的值)。即使第二次满足http / https的重定向条件,我也会绕过重定向逻辑并将" JustRedirected"会话值重置为false。您将需要自己的条件测试逻辑,但这是该属性的简单实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public bool JustRedirected
    {
        get
        {
            if (Session[RosadaConst.JUSTREDIRECTED] == null)
                return false;

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

它还取决于平衡器的品牌,对于Web多路复用器,您需要查找http标头X-WebMux-SSL-termination: true来确定传入流量为ssl。此处的详细信息:http://www.cainetworks.com/support/redirect2ssl.html


在IIS10(Windows 10和Server 2016)中,从1709版开始,提供了一个新的,更简单的选项来为网站启用HSTS。

Microsoft在这里描述了这种新方法的优点,并提供了许多不同的示例,这些示例说明了如何以编程方式或通过直接编辑ApplicationHost.config文件(类似于web.config,但在IIS级别而不是单个站点级别上运行)来实施更改。 )。可以在C: Windows System32 inetsrv config中找到ApplicationHost.config。

我在这里概述了两个示例方法,以避免链接腐烂。

方法1-直接编辑ApplicationHost.config文件
标记之间,添加以下行:

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

方法2-命令行:
在提升的命令提示符下执行以下操作(即在CMD上单击鼠标右键并以管理员身份运行)。记住用IIS管理器中出现的站点名称交换Contoso。

1
2
3
4
5
6
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

如果您在访问受限的托管环境中,Microsoft在这些文章中提供的其他方法可能是更好的选择。

请记住,IIS10版本1709现在在Windows 10上可用,但是对于Windows Server 2016,它处于不同的发行版中,并且不会作为补丁程序或Service Pack发行。有关1709的详细信息,请参见此处。


我花了一段时间寻找有意义的最佳实践,并发现了以下对我来说很完美的方法。希望这可以节省您的时间。

使用配置文件(例如,asp.net网站)

HTTP to HTTPS redirects on IIS 7.x and higher

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

[短答案]
只需下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<system.webServer>
 <rewrite>
     <rules>
       <rule name="HTTP/S to HTTPS Redirect" enabled="true"
           stopProcessing="true">
       <match url="(.*)" />
        <conditions logicalGrouping="MatchAny">
       
       </conditions>
       <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}"
        redirectType="Permanent" />
        </rule>
       </rules>
 </rewrite>

->只需在公共类HomeController:Controller的顶部添加[RequireHttps]。

->并添加GlobalFilters.Filters.Add(new RequireHttpsAttribute());在Global.asax.cs文件中的" protected void Application_Start()"方法中。

这将迫使您的整个应用程序使用HTTPS。


如果您使用的是ASP.NET Core,则可以尝试使用nuget包SaidOut.AspNetCore.HttpsWithStrictTransportSecurity。

然后,您只需要添加

1
app.UseHttpsWithHsts(HttpsMode.AllowedRedirectForGet, configureRoutes: routeAction);

这还将向使用https方案发出的所有请求添加HTTP StrictTransportSecurity标头。

示例代码和文档https://github.com/saidout/saidout-aspnetcore-httpswithstricttransportsecurity#example-code


推荐阅读

    linux检查挂载命令?

    linux检查挂载命令?,设备,系统,信息,情况,状态,服务,软件,命令,磁盘,网络,lin

    linux网站根目录命令?

    linux网站根目录命令?,系统,一致,设备,网站,目录,根目录,信息,标准,位置,电

    linux使用命令的方法?

    linux使用命令的方法?,系统,信息,工具,标准,数据,命令,左下角,目录,文件夹,

    linux一般检查命令?

    linux一般检查命令?,网络,系统,检测,情况,工作,信息,命令,进程,时间,设备,lin

    检查硬件linux命令?

    检查硬件linux命令?,信息,系统,第一,数据,设备,检测,命令,情况,灵活,实时,如

    linux访问网站的命令?

    linux访问网站的命令?,地址,系统,服务,工作,网站,命令,网络,管理,信息,网址,L

    检查路由命令linux?

    检查路由命令linux?,网络,地址,系统,信息,工具,电脑,时间,通信,服务,命令,lin

    linux数据库检查命令?

    linux数据库检查命令?,服务,状态,地址,位置,系统,信息,命令,工作,情况,密码,

    linux分区检查命令是?

    linux分区检查命令是?,系统,设备,工具,管理,情况,信息,检测,分区,密码,单位,

    linux命令行登陆网站?

    linux命令行登陆网站?,网站,系统,密码,服务,地址,环境,网络,软件,状态,项目,

    linux检查流量的命令?

    linux检查流量的命令?,工具,系统,实时,状态,网络,信息,数据,密码,地址,流量,l

    linux登陆网站命令?

    linux登陆网站命令?,网络,工具,网站,标准,地址,软件,系统,命令,数据,环境,lin

    linux命令打开网站?

    linux命令打开网站?,网络,网站,系统,地址,密码,传播,工具,代码,环境,命令,大

    linux命令行登录网站?

    linux命令行登录网站?,系统,网站,地址,工作,软件,密码,网络,第一,环境,中心,

    linux检查更新命令是?

    linux检查更新命令是?,工作,软件,地址,系统,信息,管理,命令,目录,最新,标准,l

    命令检查linux版本?

    命令检查linux版本?,系统,地址,信息,发行,名称,电脑,版本,连续,工具,周期,在L

    linux命令查询网站?

    linux命令查询网站?,地址,网络,信息,名称,档案,工具,网站,命令,传播,分析,lin

    linux内存检查命令?

    linux内存检查命令?,情况,系统,信息,工具,实时,分析,状态,内存,命令,总量,查

    linux下节点检查命令?

    linux下节点检查命令?,系统,信息,工作,名称,命令,地址,情况,文件,服务,第一,l

    linux命令输入方法?

    linux命令输入方法?,系统,电脑,密码,管理,地址,命令,网站,工具,首开,位置,lin