1

We are using load balancer and the SSL terminates at the load balancer. No https bindings have been created at the iis level for the site.

My RemoteRequiredHttps attribute wasn't working due to this reason and got it working now via this stackoverflow question.

I have created ExitHttps attribute and it follows the same rules as in above mentioned question. Exit https is not successfully happening. The page still remains in https mode even though i have applied this attribute to the action. What am i missing here?

public class ExitHttpsAttribute : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentException("Filter Context");
            }

            if (filterContext.HttpContext == null)
            {
                return;
            }

            if (!filterContext.HttpContext.Request.IsSecureConnection)
            {
                return;
            }

            var currentUrl = filterContext.HttpContext.Request.Url;
            if (!currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase))
            {
                return;
            }

            // abort if a [RequireHttps] attribute is applied to controller or action
            if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
            {
                return;
            }

            if (filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
            {
                return;
            }

            // abort if a [RetainHttps] attribute is applied to controller or action
            if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
            {
                return;
            }

            if (filterContext.ActionDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
            {
                return;
            }

            // abort if it's not a GET request - we don't want to be redirecting on a form post
            if (!String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }

            // redirect to HTTP
            var url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
            filterContext.Result = new RedirectResult(url);
        }
    }
Community
  • 1
  • 1
learning...
  • 3,104
  • 10
  • 58
  • 96

1 Answers1

0

I have updated the code to this and it is now happening

public class ExitHttpsAttribute : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentException("Filter Context");
            }

            if (filterContext.HttpContext == null)
            {
                return;
            }

            var isSecure = filterContext.HttpContext.Request.IsSecureConnection;

            var currentUrl = filterContext.HttpContext.Request.Url;
            if (!isSecure && currentUrl.Scheme.Equals(Uri.UriSchemeHttps, StringComparison.CurrentCultureIgnoreCase))
            {
                isSecure = true;
            }

            if (!isSecure && string.Equals(filterContext.HttpContext.Request.Headers["X-Forwarded-Proto"], "https", StringComparison.InvariantCultureIgnoreCase))
            {
                isSecure = true;
            }

            if (isSecure)
            {
                //in these cases keep https
                // abort if a [RequireHttps] attribute is applied to controller or action
                if (filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequireHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                // abort if a [RetainHttps] attribute is applied to controller or action
                if (isSecure && filterContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                if (isSecure && filterContext.ActionDescriptor.GetCustomAttributes(typeof (RetainHttpsAttribute), true).Length > 0)
                {
                    isSecure = false;
                }

                // abort if it's not a GET request - we don't want to be redirecting on a form post
                if (isSecure && !String.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
                {
                    isSecure = false;
                }
            }

            if (!isSecure)
            {
                return;
            }

            // redirect to HTTP
            var url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
            filterContext.Result = new RedirectResult(url);
        }
    }
learning...
  • 3,104
  • 10
  • 58
  • 96
  • Do you mean it's now working? Can you explain what you've changed and what had gone wrong? – Rup Nov 11 '14 at 00:00
  • Well in my case the load balancer is doing the SSL termination. For more details please check this out http://stackoverflow.com/questions/26849776/remote-require-https-mvc-5?noredirect=1#comment42271765_26849776. Since the request is essentially http after the load balancer to the site, i had to update the code to work in this scenario. The code now caters both my dev site which is not load balanced and the production two nodes that are load balanced. In my scenario the key was checking Headers["X-Forwarded-Proto"]. – learning... Nov 11 '14 at 03:56