ASP.NET SSL - 问题是回发,因此OnInit等不起作用

时间:2009-11-19 20:52:53

标签: asp.net ssl

我应该何时在ASP.NET页面生命周期中为安全页面强制执行SSL?

我的意思是我应该在page_load中进行吗?还是OnInit?或其他一些功能?

我使用以下代码为某些页面强制执行SSL,但是我应该在哪里放置此代码?之前我将它放在OnInit函数中,但是这对ASP.NET向导不起作用。 我是否需要首先检查是否回发?

如果回发丢弃https,我的代码不应该强制执行吗?如果回发没有丢弃https,我的代码不应该停止重定向并转到向导的下一步吗?好像它一直在重定向。

if (!HttpContext.Current.Request.IsSecureConnection) {
    HttpContext.Current.Response.Redirect(SiteNavigation.ResolveAbsoluteUrl(true, HttpContext.Current.Request.Url.PathAndQuery));
}

2 个答案:

答案 0 :(得分:2)

你基本上有两种选择。

如果您希望所有经过身份验证的页面都在SSL下运行,则可以在表单身份验证上设置requireSSL =“true”属性。只需确保您的登录页面也在HTTPS上运行。

您也可以逐页设置。我发现这在继承自System.Web.UI.Page的“页面基础”类中很有效,并且所有页面都继承自(而不是System.Web.UI.Page)。

public class PageBase : System.Web.UI.Page
{
    public bool RequiresSSL {get; set;}
    string currentPage = Request.Url.ToString();

    public PageBase()
    {
         Init += new EventHandler(PageBase_Init);
    }

    void PageBase_Init(object sender, EventArgs e)
    {
            if ((RequiresSSL) && (WebConfigurationManager.AppSettings["SSLavailable"] == "true"))
            {
                if (currentPage.ToLower().StartsWith("http://"))
                {
                    redirectTo = "https://" + currentPage.Substring(7);
                    Response.Redirect(redirectTo);
                }
            }
            else
            {
                if (currentPage.ToLower().StartsWith("https://"))
                {
                    redirectTo = "http://" + currentPage.Substring(8);
                    Response.Redirect(redirectTo);
                }
            }
    }
}

SSLavailable的AppSettings值允许您在没有SSL的测试模式下运行时关闭整个机制。

对于需要在SSL模式下运行的页面,他们需要做的就是设置RequiresSSL:

public partial class ChangePassword : PageBase
{
    public ChangePassword()
    {
        PreInit += new EventHandler(ChangePassword_PreInit);
    }

    void ChangePassword_PreInit(object sender, EventArgs e)
    {
        RequiresSSL = true;
    }
}

它非常顺畅,并且在安全页面之后转到的任何其他页面将自动切换回HTTP协议。

答案 1 :(得分:1)

我通常在OnPreLoad事件中执行此操作以强制使用SSL:

protected override void OnPreLoad(EventArgs e)
{
    base.OnPreLoad(e);
    String qs;
    qs = Request.QueryString;

    //// Force the page to be opened under SSL
    if (!Request.IsSecureConnection)
    {
        if (qs != "")
        {
            qs = "?" + qs;
        }

        Response.Redirect("https://" + 
        Request.ServerVariables["SERVER_NAME"].ToString() + 
        Request.ServerVariables["PATH_INFO"].ToString() + qs);
    }
}

如果要为所有页面强制使用SSL,则它可能非常适合HttpModule。我想出了以下内容:

using System;
using System.Web;

namespace CustomHttpModules
{
    public class EnforceSSLModule : IHttpModule
    {
        public void Init(HttpApplication httpApp)
        {
            httpApp.PreRequestHandlerExecute += this.OnPreRequestHandlerExecute;
        }

        public void Dispose()
        {
        }

        public void OnPreRequestHandlerExecute(object o, EventArgs e)
        {
            using (HttpApplication httpApp = (HttpApplication)o)
            {
                if (HttpContext.Current != null)
                {
                    HttpContext ctx = HttpContext.Current;
                    String qs;

                    qs = ctx.Request.QueryString;

                    //// Force the page to be opened under SSL
                    if (ctx.Request.IsSecureConnection)
                    {
                        if (qs != "")
                            qs = "?" + qs;

                        ctx.Response.Redirect("https://" + 
                            ctx.Request.ServerVariables["SERVER_NAME"].ToString() + 
                            ctx.Request.ServerVariables["PATH_INFO"].ToString() + qs);
                    }
                }

            }

        }
    }
}

要在IIS5.1或IIS6中使用HttpModule,请在站点的bin文件夹中删除HttpModule的已编译程序集,并将以下内容添加到web.config的HttpModules部分:

<add type="CustomHttpModules.EnforceSSLModule, dllname" name="EnforceSSLModule" />

(其中 dllname 是没有扩展名的程序集文件的名称)