Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC RequireHttps and redirect if not https

I've read thru many of the questions on ASP.NET MVC [RequireHttps] - but can't find the answer to this question:

How do you make the [RequireHttps] attribute switch the url to https if it was not https to start with?

I have this code:

public ActionResult DoSomething()
{
    return View("AnotherAction");
}

[RequireHttps]
public ActionResult AnotherAction()
{
    return View();
}

But I get an error saying: "The requested resource can only be accessed via SSL."

The MVC futures project has a similar attribute [RequireSsl(Redirect = true)]. But that is outdated now ... What is the equivalent in MVC 2?

When someone types in the URL http://example.com/home/dosomething OR the url http://example.com/home/anotheraction, I need them to be automatically redirected to the url https://example.com/home/anotheraction

EDIT this is the sequence of events:

The URL http://example.com/home/dosomething is called from another website. They redirect their users to this url (with a response.redirect or similar).

DoSomething() then tries to return AnotherAction(), but fails with the error message "The requested resource can only be accessed via SSL."

like image 666
JK. Avatar asked Mar 27 '11 04:03

JK.


3 Answers

The RequiresHttps attribute does automatically attempt to redirect to https://your-url. I verified this behavior on a site I have that uses that attribute, and also looking at the code in Reflector:

protected virtual void HandleNonHttpsRequest(AuthorizationContext filterContext)
{
    if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
    {
        throw new InvalidOperationException(MvcResources.RequireHttpsAttribute_MustUseSsl);
    }
    string url = "https://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
    filterContext.Result = new RedirectResult(url);
}

Are you sure you have your site set up to accept secure connections? What happens if you try to browse to https://your-url directly?

like image 94
Jeff Ogata Avatar answered Oct 15 '22 06:10

Jeff Ogata


[mvc 4] short answer:

protected void Application_BeginRequest(Object source, EventArgs e)
{
  if (!Context.Request.IsSecureConnection)
  {
      Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"));
  }
}

longer answer:
to move from http to https you cant send a redirect to https after the first packet,
therefor you need to catch the packet using Application_BeginRequest,
from the Global.asax add the function and it will override the default,
the code should be something like so (Global.asax on the class level):

protected void Application_BeginRequest(Object source, EventArgs e)
{
  if (!Context.Request.IsSecureConnection && 
      !Request.Url.Host.Contains("localhost") && 
      Request.Url.AbsolutePath.Contains("SGAccount/Login"))
  {
      Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"));
  }
}

i strongly suggest putting a breakpoints and inspecting the Request.Url object for any url related need.
or visit the msdn page confused about request.url absoluteuri vs originalstring?
so am i you can go to dotnetperls for examples.
this function enables you to develop on localhost and deploying your code as is.
now for every page you want to make a https redirect you need to specify it in the if condition.
to move from https to http you can use regular Response.Redirect like so:

if (Request.Url.Scheme.Contains("https"))
{
    Response.Redirect(string.Format("http://{0}", Request.Url.Authority), true);
}

notice this also support working on the same code when developing on local host by not interrupting the original course of things pre the https addition.

also i recommend thinking about implementing some return url convention (if not already implemented) in that case you should go something like so:

if (Request.Url.Scheme.Contains("https"))
{
    Response.Redirect(string.Format("http://{0}{1}", Request.Url.Authority, returnUrl), true);
}

this will redirect to the requested page post login.

naturally you should protect every page that shows user data, register, login and more.

like image 20
Yakir Manor Avatar answered Oct 15 '22 06:10

Yakir Manor


Http HEAD requests do not appear to be redirected. When reviewing our error logs we see lots of this message, googling lands here, but after looking more at the details they have a few interesting "features"

  • Request_method: HEAD
  • User Agent: curl/7.35.0

In other words all of the failed attempts were not customer facing...

(100% credit to comment from @arserbin3 for making me realize they were all HEAD requests)

like image 3
Aaron Sherman Avatar answered Oct 15 '22 06:10

Aaron Sherman