Caching Roles For Better Site Performance
If you use roles in your ASP.NET application, by default ASP.NET queries the database with every page request in order to fetch the list of roles the current user belongs to. Considering the performance overhead that entails, it's surprising that so many developers forget to enable role caching in their applications.
Roles are a convenient way to manage authorization in a ASP.NET application. Roles are enabled in the web.config file as follows:
<roleManager enabled="true" />
Once you've enabled role management, you can do some pretty nifty stuff, like limiting access to files in a given folder to those users belonging to a particular role:
<location path="Manager">
<system.web>
<authorization>
<allow roles="Manager"/>
<deny users="*"/>
authorization>
system.web>
location>
It allows us to take advantage of Web controls that leverage the role manager, like the LoginView control:
<asp:LoginView ID="LoginView1" runat="server">
<RoleGroups>
<asp:RoleGroup Roles="Manager">
<ContentTemplate>
<p>
Hi there! You are a Manager!p>
ContentTemplate>
asp:RoleGroup>
<asp:RoleGroup Roles="Employee">
<ContentTemplate>
<p>
Hi there! You are an Employee!p>
ContentTemplate>
asp:RoleGroup>
RoleGroups>
<LoggedInTemplate>
<p>
Hi there! You belong to no roles.p>
LoggedInTemplate>
asp:LoginView>
It also allows us to conveniently inquire whether the current user belongs to a given role directly from the User property of the current Page, without a reference to System.Web.Security:
protected void Page_Load(object sender, EventArgs e)
{
if (this.User.IsInRole("Manager"))
Label1.Text = "You are a Manager.";
// TODO: add code here to set up the page
// to allow user to perform Manager duties
else
Label1.Text = "You are NOT a Manager.";
}
How Role Management Works
In order to fulfill these requests, the ASP.NET runtime must obviously posess awareness of not only who the user is, but what roles the user belongs to. We know that ASP.NET "knows" who the current user is by reading the contents of the authentication cookie sent by the browser request. But authentication cookies contain no role information at all. So, how does the ASP.NET runtime "know" what roles the current user belongs to, in order to issue the correct response?
By default, the role manager supports this functionality by issuing a query to the database (as specified by the current role provider) for every page request. That's a lot of database hits! Wouldn't it be great if we could easily cache the list of roles, and save all those round trips?
Caching Roles
It turns out we can do just that.
<roleManager
enabled="true"
cacheRolesInCookie="true"
createPersistentCookie="true"
cookieTimeout="1440" />
Setting cacheRolesInCookie="true" makes the role management system work more like the Membership system does. This way, the runtime will first look for a cookie that contains the list of roles for the current user (by default, this cookie is named .ASPXROLES). If the cookie exists, a trip to the database is avoided (yay!). If it doesn't find one, it retrieves the current user's roles from the database, then sets a new roles cookie, returning it with the current response. The cookie is then used for future page requests. The role manager won't hit the database again until the cookie expires.
By default, the roles cookie is session-based, and is lost when the session dies. By setting createPersistentCookie="true", the cookie will be saved on the user's computer and will be available across multiple sessions. You can set the expiration date by setting the cookieTimeout value in minutes.
Keeping the Cache Up to Date
Of course, like any cache, the information in the roles cookie can become stale, and nobody likes stale cookies (sorry, bad joke ;). If you update role information on the server, the cookie won't reflect those changes. This means you have to remember to call the Roles.DeleteCookie() method whenever you alter role information from the application, which forces the server to issue a new cookie with the next page request.
protected void DemoteManager(string userName)
{
if Roles.IsUserInRole(userName, "Manager"))
{
Roles.RemoveUserFromRole(userName, "Manager");
Roles.DeleteCookie();
}
}
As you can see, caching roles in a cookie is an easy way to improve performance for ASP.NET sites which use role-based authorization.
Subscribe to this blog for more cool content like this!
Pingback from Caching Roles For Better Site Performance
You've been kicked (a good thing) - Trackback from DotNetKicks.com
Thank you for submitting this cool story - Trackback from DotNetShoutout