在开发网站的过程中,经常需要在安全(HTTPS/SSL)和非安全(HTTP/非SSL)页面之间进行切换。这种切换不仅关系到网站的安全性,还涉及到搜索引擎优化(SEO)的问题。本文将介绍一种实现HTTP与HTTPS自动切换的方法,旨在提高网站的安全性,同时确保SEO效果不受影响。
在研究HTTP与HTTPS切换问题时,发现了一些解决方案。Matt Sollars提出了一种基于web.config的方法,可以强制整个目录或单个页面使用SSL。Yohan B提出了一种基于Attribute的方法,通过在页面上添加RequireSSL属性来指定页面必须使用SSL。这些方法虽然有效,但实现起来较为复杂,且在进行HTTP与HTTPS切换时,直接使用Response.Redirect()方法,对SEO并不友好。
将采用一种新的方法来实现HTTP与HTTPS的自动切换。将使用Attribute来标记需要SSL的页面,并实现一个自定义的HTTP模块,负责拦截对ASPX页面的请求,并在必要时进行HTTP与HTTPS的切换。同时,还将探讨如何在SEO友好的方式下实现这一功能。
首先,需要定义一个Attribute,以便可以在需要SSL的页面上使用这个Attribute进行标记。定义了一个名为RequireSSL的Attribute:
public sealed class RequireSSL : Attribute
{
}
在示例项目中,login.aspx和signup.aspx页面需要使用SSL。将相应地标记它们:
[RequireSSL]
public partial class login : System.Web.UI.Page
{
// ...
}
[RequireSSL]
public partial class signup : System.Web.UI.Page
{
// ...
}
接下来,将实现自定义的HTTP模块。将配置该模块,以便HTTP与HTTPS的切换代码仅在编译为Release模式时运行:
public class RequireSSLModule : IHttpModule
{
public void Init(HttpApplication context)
{
#if !DEBUG
context.PreRequestHandlerExecute += new EventHandler(OnPreRequestHandlerExecute);
#endif
}
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
System.Web.UI.Page page = HttpContext.Current.Handler as System.Web.UI.Page;
if (page == null) return;
bool requireSSL = page.GetType().GetCustomAttributes(typeof(RequireSSL), true).Length > 0;
bool isSecureConnection = HttpContext.Current.ApplicationInstance.Request.IsSecureConnection;
Uri baseUri = HttpContext.Current.ApplicationInstance.Request.Url;
if (requireSSL && !isSecureConnection)
{
string url = baseUri.ToString().Replace(baseUri.Scheme, Uri.UriSchemeHttps);
PermanentRedirect(url);
}
else if (!requireSSL && isSecureConnection)
{
string url = baseUri.ToString().Replace(baseUri.Scheme, Uri.UriSchemeHttp);
PermanentRedirect(url);
}
}
private void PermanentRedirect(string url)
{
HttpContext.Current.Response.Status = "301 Moved Permanently";
HttpContext.Current.Response.AddHeader("Location", url);
}
}
代码中已经添加了注释,应该很容易理解。这里需要注意的几点是:代码仅在必要时进行HTTP与HTTPS的切换;只有标记了RequireSSL模块的页面才允许使用SSL,这些页面将被重定向到HTTPS,而所有其他页面将自动重定向到使用HTTP;PermanentRedirect()方法执行301重定向,这是对搜索引擎最友好的重定向方式。
现在,需要在web.config文件中注册RequireSSL模块。可以在以下两个位置安全地注册该模块,这样就不必担心网站是在IIS6还是IIS7上运行了。
对于IIS6或IIS7运行在Classic Mode:
<configuration>
<system.web>
<httpModules>
<add name="RequireSSL" type="Code.RequireSSLModule, Code" />
</httpModules>
</system.web>
</configuration>
对于IIS7运行在Integrated Mode:
<configuration>
<system.webServer>
<modules>
<add name="RequireSSL" preCondition="managedHandler" type="Code.RequireSSLModule, Code" />
</modules>
</system.webServer>
</configuration>