Moving between HTTP and HTTPS in ASP.NET MVC

前端 未结 2 1236
有刺的猬
有刺的猬 2020-12-28 22:49

So I\'ve found the [RequiresHttps] attribute but once your in https your kind of stuck there, so to try and be able to have actions on a single url (and scheme) I\'ve found

相关标签:
2条回答
  • 2020-12-28 23:09

    To make it little more manageable. This solution assumes that majority of your web application use HTTP scheme.

    1. Create new action filter RequiresHttp (use HTTP if NeedSsl attribute is not apply explicitly on action or controller),

      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. And new blank attribute NeedSSL (for indication purpose)

      [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
      public sealed class NeedSslAttribute : Attribute { }
      
    3. Apply RequiresHttp as global action filter in Global.aspx.cs

      public static void RegisterGlobalFilters(GlobalFilterCollection filters)
      {
          filters.Add(new RequiresHttp());
      }
      
    4. Now apply apply NeedSslAttribute on controllers and actions where do you want to use HTTPS scheme

      [NeedSsl]
      [AllowAnonymous]
      public ActionResult LogOn()
      

    This code is not perfect as action filter RequiresHttp does multiple jobs i.e. check NeedSsl attribute and apply HTTP or HTTPS scheme. Would have been better if we could use two action filters RequiresHTTP and RequiresHTTPS.

    Now if RequiresHTTP was set as global filter and RequiresHTTPS filter was applied on specific actions and specific RequiresHTTPS filter would have given preference.

    0 讨论(0)
  • 2020-12-28 23:27

    What you have is syntatically correct, however a suggestion is to create a new Action filter that inherits from the default RequireHttpsAttribute and takes a parameter to switch between http and 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);
            }
        } 
    }
    

    Then, on your action method or controller you would use:

    [RequireHttps (RequireSecure = true)]
    

    ...

    or

    [RequireHttps (RequireSecure = false)]
    
    0 讨论(0)
提交回复
热议问题