在ASP.NET MVC中在HTTP和HTTPS之间移动

时间:2010-11-25 13:59:26

标签: asp.net-mvc

所以我找到了[RequiresHttps]属性,但是一旦你在https中你的那种卡在那里,那么试着能够对一个网址(和方案)进行操作我发现我已经结束了必须创建我自己的ExtendedController以恢复为不使用[RequireHttps]的动作的http。

只是想知道我在做什么是好的还是有更好的方法?

public class ExtendedController : Controller
{
    protected virtual void HandleHttpRequest(AuthorizationContext filterContext)
    {
        if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("Cannot post between https and http.");
        }
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);
        object[] attributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
        if (!attributes.Any(a => a is RequireHttpsAttribute))
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.HttpContext.Request.IsSecureConnection)
            {
                this.HandleHttpRequest(filterContext);
            }
        }
    }
}

2 个答案:

答案 0 :(得分:11)

你所拥有的是语法上正确的,但是建议创建一个新的Action过滤器,它继承自默认的RequireHttpsAttribute,并使用一个参数在http和https之间切换。

public class RequireHttpsAttribute : System.Web.Mvc.RequireHttpsAttribute
{
    public bool RequireSecure = false;

    public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)

    {
        if (RequireSecure)
        {
            base.OnAuthorization(filterContext);
        }
        else
        {
            // non secure requested
            if (filterContext.HttpContext.Request.IsSecureConnection)
            {
                HandleNonHttpRequest(filterContext);
            }
        }
    }

    protected virtual void HandleNonHttpRequest(AuthorizationContext filterContext)
    {
        if (String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            // redirect to HTTP version of page
            string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
            filterContext.Result = new RedirectResult(url);
        }
    } 
}

然后,在您的操作方法或控制器上,您将使用:

[RequireHttps (RequireSecure = true)]

...

[RequireHttps (RequireSecure = false)]

答案 1 :(得分:1)

使其更易于管理。此解决方案假设您的大多数Web应用程序使用 HTTP 方案。

  1. 创建新的操作过滤器RequiresHttp(如果NeedSsl属性未明确应用于操作或控制器,则使用HTTP),

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        HttpRequestBase req = filterContext.HttpContext.Request;
        HttpResponseBase res = filterContext.HttpContext.Response;
    
        bool needSsl = filterContext.ActionDescriptor.IsDefined(typeof(NeedSslAttribute), true)
                        || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(NeedSslAttribute), true);
    
    
        if (needSsl && !req.IsSecureConnection) //https: secure
        {
            var builder = new UriBuilder(req.Url)
            {
                Scheme = Uri.UriSchemeHttps,
                Port = 444
            };
            res.Redirect(builder.Uri.ToString());
        }
        else if (!needSsl && req.IsSecureConnection) //http: non secure
        {
            var builder = new UriBuilder(req.Url)
            {
                Scheme = Uri.UriSchemeHttp,
                Port = 8081
            };
            res.Redirect(builder.Uri.ToString());
        }
        base.OnActionExecuting(filterContext);
    }
    
  2. 新的空白属性NeedSSL(用于指示)

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class NeedSslAttribute : Attribute { }
    
  3. 在Global.aspx.cs中将RequiresHttp应用为全局操作过滤器

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new RequiresHttp());
    }
    
  4. 现在在控制器和操作上应用NeedSslAttribute,你想在哪里使用HTTPS方案

    [NeedSsl]
    [AllowAnonymous]
    public ActionResult LogOn()
    
  5. 此代码并不完美,因为操作过滤器RequiresHttp会执行多个作业,即检查NeedSsl属性并应用HTTPHTTPS方案。如果我们可以使用两个操作过滤器RequiresHTTPRequiresHTTPS,那会更好。

    现在,如果RequiresHTTP设置为全局过滤器,并且RequiresHTTPS过滤器已应用于特定操作,则特定RequiresHTTPS过滤器会优先使用。