在asp.net强制https整个网站的最佳途径?
大约6个月前,我推出了一个网站,每个请求都需要通过https。 当时我能find的唯一方法是确保对页面的每个请求都通过https来检查页面加载事件。 如果请求不是通过http我会response.redirect(“ https://example.com ”)
有没有更好的方法 – 理想情况下在web.config中的一些设置?
请使用HSTS
从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>
原始答复
基本上
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 。 浏览器必须支持这个function(目前主要是Chrome和Firefox),但是这意味着一旦设置,浏览器就不会通过HTTP向站点发出请求,而是在发布之前将其转换为HTTPS请求。 。 试试这个结合来自HTTP的redirect:
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模块将让你redirect。
<rewrite> <rules> <rule name="Redirect HTTP to HTTPS" stopProcessing="true"> <match url="(.*)"/> <conditions> <add input="{HTTPS}" pattern="^OFF$"/> </conditions> <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/> </rule> </rules> </rewrite>
对于那些使用ASP.NET MVC。 您可以使用以下两种方式通过HTTPS在整个站点上强制使用SSL / TLS:
艰难的路
1 – 将RequireHttpsAttribute添加到全局filter:
GlobalFilters.Filters.Add(new RequireHttpsAttribute());
2 – 强制防伪令牌使用SSL / TLS:
AntiForgeryConfig.RequireSsl = true;
3 – 要求Cookie通过更改Web.config文件来默认要求HTTPS:
<system.web> <httpCookies httpOnlyCookies="true" requireSSL="true" /> </system.web>
4 – 使用NWebSec.Owin NuGet软件包并添加以下代码行以启用跨站点的严格传输安全性。 不要忘记在下面添加Preload指令,并将您的站点提交到HSTS Preload站点 。 更多信息在这里和这里 。 请注意,如果您不使用OWIN,则可以在NWebSec站点上查阅 Web.config方法。
// app is your OWIN IAppBuilder app in Startup.cs app.UseHsts(options => options.MaxAge(days: 30).Preload());
5 – 使用NWebSec.Owin NuGet程序包并添加以下代码行以在整个站点上启用公用密钥locking(HPKP)。 更多信息在这里和这里 。
// app is your OWIN IAppBuilder app in Startup.cs app.UseHpkp(options => options .Sha256Pins( "Base64 encoded SHA-256 hash of your first certificate eg cUPcTAZWKaASuYWhhneDttWpY3oBAkE3h2+soZS7sWs=", "Base64 encoded SHA-256 hash of your second backup certificate eg M8HztCzM3elUxkcjR2S5P4hhyBNf6lHkmjAHKhpGPWE=") .MaxAge(days: 30));
6 – 将httpsscheme包含在任何使用的URL中。 内容安全策略(CSP) HTTP头和子资源完整性(SRI)在您在某些浏览器中模仿该scheme时效果不佳 。 明确HTTPS更好。 例如
<script src="ajax/bootstrap/3.3.4/bootstrap.min.js"></script>
简单的方法
使用ASP.NET MVC Boilerplate Visual Studio项目模板生成一个包含所有这些内置项目的项目。您还可以在GitHub上查看代码。
如果你不能在任何原因在IIS中设置它,我会做一个HTTP模块为你做redirect:
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中:
<httpModules> <add name="HttpsOnlyModule" type="HttpsOnly.HttpsOnlyModule, HttpsOnly" /> </httpModules>
你需要做的是:
1)在web.config中添加一个密钥,具体取决于下面的生产或阶段服务器
<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); } } } }
这也取决于您的平衡器的品牌,对于networking多路复用器,您需要查找http标头X-WebMux-SSL-termination: true
来确定传入stream量是否为ssl。 详细信息在这里: http : //www.cainetworks.com/support/redirect2ssl.html
如果SSL支持在您的站点中是不可configuration的(即,应该能够打开/closureshttps) – 您可以在您希望保护的任何控制器/控制器操作上使用[RequireHttps]属性。
对于上面的@Joe,“这是给我一个redirect循环。在我添加代码之前,它工作得很好。有什么build议? – 乔11月8日11日在4:13”
这种情况也发生在我身上,我相信发生的事情是有一个负载均衡器终止Web服务器前面的SSL请求。 所以,我的网站总是认为请求是“http”,即使原始浏览器要求它是“https”。
我承认这有点冒险,但是对我来说有效的是实现一个“JustRedirected”属性,我可以利用这个属性来弄清楚这个人已经被redirect了一次。 所以,我testing的redirect的具体条件,如果他们符合,我在redirect之前设置此属性(存储在会话中的值)。 即使第二次满足redirect的http / https条件,我也会绕过redirect逻辑并将“JustRedirected”会话值重置为false。 你将需要你自己的条件testing逻辑,但是这里有一个简单的属性实现:
public bool JustRedirected { get { if (Session[RosadaConst.JUSTREDIRECTED] == null) return false; return (bool)Session[RosadaConst.JUSTREDIRECTED]; } set { Session[RosadaConst.JUSTREDIRECTED] = value; } }
我打算把我的两分钱。 如果你有访问IIS服务器端,那么你可以通过使用协议绑定强制HTTPS。 例如,您有一个名为Blah的网站。 在IIS中,您将设置两个站点: Blah和Blah(redirect) 。 对于Blah,只能configurationHTTPS
绑定(如果需要,还可以使用FTP
,确保也通过安全连接强制执行)。 对于Blah(redirect),只configurationHTTP
绑定。 最后,在Blah(redirect)的HTTPredirect部分中,确保将301redirect设置为https://blah.com
,并启用确切的目的地。 确保IIS中的每个站点都指向它自己的根文件夹,否则Web.config将全部搞砸。 另外,请确保在HTTPSed站点上configuration了HSTS
,以便浏览器的后续请求始终强制为HTTPS,并且不会发生redirect。
– >在公共类HomeController:Controller上简单地添加[RequireHttps]。
– >并添加GlobalFilters.Filters.Add(新的RequireHttpsAttribute()); 在Global.asax.cs文件的'protected void Application_Start()'方法中。
这将强制您的整个应用程序使用HTTPS。
这是基于@Troy Hunt的更全面的答案。 将此函数添加到Global.asax.cs
的WebApplication
类中:
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; } } }
(要在本地构build中启用SSL,请在项目的“属性”对话框中启用它)
如果您正在使用ASP.NET Core,则可以尝试使用nuget包SaidOut.AspNetCore.HttpsWithStrictTransportSecurity。
那么你只需要添加
app.UseHttpsWithHsts(HttpsMode.AllowedRedirectForGet, configureRoutes: routeAction);
这也会将HTTP StrictTransportSecurity标头添加到使用httpsscheme进行的所有请求。
示例代码和文档https://github.com/saidout/saidout-aspnetcore-httpswithstricttransportsecurity#example-code
http模块的另一个优点是,如果你只在global.asax.cs中提供它,它只在Application_BeginRequest上检查SSL,这意味着你的应用程序没有被完全保护。 它只会首先路由到SSL版本,然后用户可以剪切和粘贴没有SSL的URL并绕过它。