views:

186

answers:

3

Besides simply redirecting from HTTP to HTTPS, the RequireHttps attribute also changes my URL's question mark ? to %3F. Unsurprisingly, that breaks things.

Why? How do I fix it?

scenario:

  1. I try to navigate to http://www.example.com/message/compose

  2. But let's say I don't have permission to view that page.

    <HandleError()> _
    Public Class MessageController
        Inherits System.Web.Mvc.Controller
    
    
    
    Function Compose() As ActionResult
        ...
        If ... Then
            Throw New Exception(Net.HttpStatusCode.Unauthorized.ToString)
        End If
        ...
        Return View()
    End Function
    
    
    ...
    
    End Class
  3. The action throws an exception.

  4. The exception is handled by my Error.aspx page

    <%@ Page Language="VB" Inherits="System.Web.Mvc.ViewPage(Of System.Web.Mvc.HandleErrorInfo)" %>
    
    
    <script runat="server">
        Sub Page_Load(ByVal Sender As System.Object, ByVal e As System.EventArgs)
            If Model.Exception.Message = Net.HttpStatusCode.Unauthorized.ToString Then
                response.redirect("/signin?ReturnUrl=" + Url.Encode(request.Path))
            End If
            ...
        End Sub
    </script>
    
    
    ...
    
  5. I'm redirected to my Sign In page at http://www.example.com/signin?ReturnUrl=%2fmessage%2fcompose

  6. But I'm using HTTP and not HTTPS. My action requires HTTPS. (That RemoteRequireHttps inherits from RequireHttps and overrides its OnAuthorization method to simply disregard localhost.)

    <HandleError()> _
    Public Class AccountController
        Inherits System.Web.Mvc.Controller
    
    
    
    &lt;RemoteRequireHttps()&gt; _
    Function SignIn() As ActionResult
        ...
    End Function
    
    
    ...
    
    End Class
  7. I'm redirected to https://www.example.com/signin%3FReturnUrl=%2fmessage%2fcompose

  8. I see this error in my browser:

Bad Request

It seems that RequireHttps changes my question mark ? to %3F.

+1  A: 

We're considering using a URL rewriter like ISAPI Rewrite to handle things like this before they ever get to your code. Of course, this would only work if you have access to the server.

Also, if you're using IIS 7, I believe it comes with URL rewriting functionality built in.

Shea Daniels
It might be a better to handle it in IIS. I can't think of any uses where it would necessarily have to be at the application level.
Zack Peterson
A: 

I've just reengineered this to avoid the question mark (and also exception throws) altogether.

scenario:

I try to navigate to http://www.example.com/message/compose

But let's say I don't have permission to view that page.

Public Class MessageController
    Inherits System.Web.Mvc.Controller

    Function Compose() As ActionResult
        ...
        If ... Then
            Return RedirectToAction("SignIn", "Account", New With {.ReturnUrl = Request.Path})
        End If
        ...
        Return View()
    End Function

    ...

End Class

I'm redirected to my Sign In page. My route looks like this:

routes.MapRoute( _
    "SignIn", _
    "signin/{*ReturnUrl}", _
    New With {.controller = "Account", _
              .action = "SignIn", _
              .ReturnUrl = ""} _
)

So that's at address http://www.example.com/signin/message/compose

But I'm using HTTP and not HTTPS. My action requires HTTPS.

Public Class AccountController
    Inherits System.Web.Mvc.Controller

    <RemoteRequireHttps()> _
    Function SignIn(ByVal ReturnUrl As String) As ActionResult
        ...
    End Function

    ...

End Class

I'm redirected to https://www.example.com/signin/message/compose

No question mark. No problem.

Zack Peterson
+1  A: 

My answer to my own question here might help (appears to be a bug in MVC 2 Preview 2)

Can I ask why you're not using [Authorize] or a custom authorization attribute. If you're using .NET authentication you should use [Authorize].

Note: even if you do use [Authorize] it doesnt actually fix the problem you're experiencing.

Simon_Weaver