Setup
I am using custom Forms Authentication – all standard stuff.
In the Login action on my Account controller,
- I check the user’s details against the db
- If successful I create a Forms Authentication ticket
- Store the logged in members db row id in UserData in the ticket
- Encrypt the ticket
- Store the ticket in a cookie
- Add the cookies to the Reponse.Cookies collection
- Redirect to Index Action on Home Controller
I registered a handler in global asax for the AuthenticateRequest event. In my handler,
- I retrieve the cookie from HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
- If the cookie exists I decrypt the value of the Forms Authentication ticket in the cookie
- Retrieve the user’s details from the db using the Id stored in the authentication ticket UserData.
- Create a custom principal and set the user (it has a custom LoggedInUser property) to the user I retrieved from the db.
- Set the HttpContext.Current.User to the custom principal
Problem
I debug a request for the home page after I have logged in and note that the AuthenticateRequest handler in global.asax is hit more than once per page request. I’ve checked the HttpContext.Current.Request.Path and this is because each resource on my page (effectively, every HTTP GET) is firing the authenticate requet, so, GET jquery.js, GET logo.png etc…
Question
On the first handled AuthenticateRequest I go to the db and then set the HttpContext.Current.User to my custom principal. What would be a good way to avoid going to the db for subsequent HTTP GETs that cause the AuthenticatRequest to fire. Effectively, authenticate once and once only until the user closes their browser or until the Authentication Ticket expires.
TIA
Instead of using the
AuthenticateRequestmethod in your Global.asax I would recommend you writing a global action filter. This way the action filter will apply only before executing some action and populate the User. In fact a custom[Authorize]attribute is the best way to achieve that: