2010-11-25 33 views
8

所以我找到了[RequiresHttps]屬性,但是一旦你在https中你的那種卡住了,所以嘗試和能夠對一個URL(和方案)我發現我最終不得不創建自己的擴展控制器來恢復爲不使用[RequireHttps]的動作。在ASP.NET MVC中的HTTP和HTTPS之間移動

只是想知道我在做什麼好或者如果有更好的方法嗎?

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); 
      } 
     } 
    } 
} 
+0

我剛剛意識到的一件事是我還應該檢查filterContext.IsChildAction - 我想知道是否有可能在子動作上使用RequiresHttp運行相同的問題。似乎需要一個更完整的解決方案,可能在路由一側而不是控制器上。 – Mark 2010-11-25 14:05:11

回答

11

你有什麼是syntatically正確的,但是一個建議是建立一個新的動作過濾器,從默認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)] 
+0

有一點需要注意的是,這個默認是非安全的「public bool RequireSecure = false;」而System.Web.Mvc.RequireHttpsAttribute需要HTTPS。如果你想平行System.Web.Mvc.RequireHttpsAttribute,只需將默認值設置爲「true」即可。 – ChrisP 2014-02-19 22:26:39

1

爲了使它更易於管理。此解決方案假定您的大多數Web應用程序使用HTTP方案。

  1. 創建新動作過濾器RequiresHttp(使用HTTP如果NeedSsl屬性不行動或控制器明確應用),

    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. 現在應用上的控制器和動作要使用HTTPS方案

    [NeedSsl] 
    [AllowAnonymous] 
    public ActionResult LogOn() 
    

此代碼是不完美的,因爲行爲過濾RequiresHttp沒有多個作業,即檢查NeedSsl屬性和應用在哪裏申請NeedSslAttribute HTTPHTTPS方案。如果我們可以使用兩個動作過濾器RequiresHTTPRequiresHTTPS會更好。

現在,如果RequiresHTTP設置爲全局過濾器,並且RequiresHTTPS過濾器應用於特定操作並且特定RequiresHTTPS過濾器將給予優先。

相關問題