Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cookieless sessions and cross-site form posts

Here's the situation...

Site 1) ASP.NET MVC application for customers to login, view and pay bills, etc. This site is using cookieless ASP sessions to allow multiple sessions to run in tabbed browsers.

Site 2) Corporate web site with standard static content. This will have a small form at the top of each page with a username/password form that will post to the MVC application.

When posting to the MVC app, a new session is being generated and the site is returning a 302 redirect with the session ID in the URL (as expected). The controller has two Login methods, one for handling a GET, one for handling a POST. Because of the redirect, it's hitting the GET method and it loses the form values.

By changing the method on the corporate site to do a form GET rather than a POST, the username and password are preserved in the query string after the redirect and I could handle the requests that way, but I would rather do a POST and not pass that data around in the URL.

My gut says that implementing some sort of custom HttpHandler would allow me to do this, but I'm not sure where I'd be able to tie into the session creation. A breakpoint at Session_Start in global.asax shows that the session ID has already been crated and the redirect already happened at that point.

like image 938
Pete Nelson Avatar asked Nov 06 '22 18:11

Pete Nelson


1 Answers

I believe I found where the redirect was happening as well as a possible solution to it. The ISessionIDManager interface has a SaveSessionID method with an "out bool redirected" parameter on it. It appears that when a new session is created, the default session manager rewrites the URL inside this method and does a redirect. I played around with implementing my own ISessionIDManager and I was able to suppress the redirect, but there's no way (that I could tell) of inserting the session ID into the URL for the cookieless session without doing the redirect. Server.Transfer is not allowed at that point in the request lifecycle. I tried that but received an "Error Executing Child Request" message.

Later on, I found this article on Enabling POST in cookieless ASP.NET Applications. Basically by tying in to the Application_EndRequest event, you can detect the redirect, clear the response and fake a form post to the new URL that contains the session ID.

void MvcApplication_EndRequest(object sender, EventArgs e)
{

    HttpApplication application = (HttpApplication)sender;

    if (application.Request.Form["CorpLogin"] == "1"
        && application.Response.RedirectLocation != null
        && application.Response.IsRequestBeingRedirected)
    {

        StringBuilder build = new StringBuilder();
        build.Append("<html>\n<body>\n<form name='Redirect' method='post' action='");
        build.Append(application.Response.RedirectLocation);

        build.Append("' id='Redirect' >");
        foreach (string key in application.Request.Form)
        {
            if (key != "CorpLogin")
                build.Append(string.Format("\n<input type='hidden' name='{0}' value = '{1}'>", (string)key, application.Request.Form[(string)key]));
        }

        build.Append("\n<noscript><h2>Object moved <input type='submit' value='here'></h2></noscript>");
        build.Append(@"</form>
      <script language='javascript'>
      <!--
        document.Redirect.submit();
      // -->
      </script>
      ");
        build.Append("</body></html>");

        application.Response.Clear();
        application.Response.ClearHeaders();
        application.Response.Output.Flush();

        application.Response.Write(build.ToString());

    }
}

This isn't an ideal solution IMHO but it might be workable enough to meet the requirements.

like image 103
Pete Nelson Avatar answered Nov 15 '22 13:11

Pete Nelson