views:

26

answers:

2

I'm using Application_OnAuthenticateRequest in Global.asax to assign a custom principal to HttpContext.Current.User and System.Threading.Thread.CurrentPrincipal.
In testing, I noticed that this code executes multiple times for a single page request. By looking at the HttpContext.Current.Request.Url I determined that this code is executing for each call to a JavaScript file, Image, and CSS file. All of these resources are stored in a single subfolder called "Content". So, I'm able to prevent multiple executions of my custom principal by checking to see if "Content" is part of HttpContext.Current.Request.Url like so:

protected void Application_OnAuthenticateRequest(Object sender, EventArgs e)
{
    if (HttpContext.Current.Request.Url.AbsoluteUri.Contains("/Content"))
        return;

    if (Context.User != null)
    {
        if (Context.User.Identity.IsAuthenticated)
        {
            var userRepository = ObjectFactory.GetInstance<IUserRepository>();

            var prospectorUser = userRepository.GetByUserName(Context.User.Identity.Name);

            if (prospectorUser == null)
            {
                throw new ApplicationException("Context.User.Identity.Name is not a recognised user.");
            }

            var principal = new ExtendedWindowsPrincipal(HttpContext.Current.User.Identity, prospectorUser);

            // Attach the new principal object to the current HttpContext object
            HttpContext.Current.User = principal;
            // Make sure the Principal's are in sync
            System.Threading.Thread.CurrentPrincipal = HttpContext.Current.User;
            return;
        }
    }
}

My fix seems kludgy. Is there a better way to trap requests for "Content" items and prevent my custom code for my principal from firing for every request?

A: 

The simple answer is the modify your web.config to make the 'Content' folder anonymously accessible:

<location path="Content">
    <system.web>
        <authorization>
            <allow users ="*" />
        </authorization>
    </system.web>
</location>
Scrappydog
I thought this too initially, but my hunch is that AuthenticateRequest is still going to fire, and hence execute his kludge. Would love some confirmation on that though.
womp
Should only take a minute to test...
Scrappydog
I commented out my check for "Content" in Application_OnAuthenticateRequest then added the <location>..</location> to my web.config and it did not make a difference. My principal code would fire for all content related requests.
Tom Schreck
A: 

The AuthenticateRequest event occurs pretty high up in the HTTP pipeline. If you want to bypass it in certain cases for your application, you'll probably need to write an HttpModule that is registered to handle a given path.

Take a look at Figure 9, 10 and 11 in the article below. You should be able to follow it to build a custom module to handle requests to the Content path, and bypass all the regular event processing.

Securely Implement Request Processing, Filtering, and Content Redirection with HTTP Pipelines in ASP.NET

womp
My initial attempt at this approach ended up preventing the resources in the Content folder from being downloaded to client. So, no images, CSS, scripts, etc. I created a httpModule which intercepts requests. If the request contained "content" in uri, then I completed request and set the response code to 200, but none of the resources are being sent to client.
Tom Schreck
You probably can't just complete the request - you'll still need to pass the request off to an IHttpHandler that will send the content, or manually send the file yourself.
womp