My musings about .NET and what not

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!

kick it on DotNetKicks.com

shout it on DotNetShoutOut.com

vote it on WebDevVote.com

Bookmark / Share

    » Similar Posts

    1. Managing Anonymous Users For Better Site Performance
    2. How To Let Users Change Their Email Address in TheBeerHouse Starter Kit
    3. Resetting the Page Index in a ListView

    » Trackbacks & Pingbacks

    1. Pingback from Caching Roles For Better Site Performance

      Caching Roles For Better Site Performance — January 4, 2009 2:57 PM
    2. You've been kicked (a good thing) - Trackback from DotNetKicks.com

      Caching Roles For Better Site Performance — January 6, 2009 9:10 AM
    3. Thank you for submitting this cool story - Trackback from DotNetShoutout

      Caching Roles For Better Site Performance : LeeDumond.com — January 7, 2009 2:49 PM
    Trackback link for this post:
    http://leedumond.com/trackback.ashx?id=33

    » Comments

    1. adebayo avatar

      Thanks for the info. I have a question: Does this create a security issue? Can't someone try to "guess" what the admin role is and modify the page's cookie until they get it right? I suppose if you do this cookie method, you can make your roles look like passwords or something (i.e. "fjd832kl8" so that somebody would never guess the admin role).

      adebayo — March 3, 2009 7:26 PM
    2. Lee Dumond avatar

      That's an interesting question. Give me a few days to investigate this further and I'll leave a response here on what I find out.

      Lee Dumond — March 4, 2009 10:13 AM
    3. shola avatar

      Very helpful blog. Any insight on the above question about security? I might test it out myself when I get back on my dev computer this week.

      shola — March 11, 2009 12:16 AM
    4. Lee Dumond avatar

      @Shola - I've been trying to get a book out and haven't had time to play with this, but I still intend to investigate it. If you do, please let us know what you find out...

      Lee Dumond — March 11, 2009 11:01 AM
    5. shola avatar

      Hey, I actually took a look at the security issue. apparently asp.net doesn't encrypt the roles cookie name, but it encrypts the roles cookie value (which is the important thing anyway). I used the nifty firefox plugin here addons.mozilla.org/.../315

      so I suppose all is well!

      shola — March 14, 2009 4:17 AM
    6. Lee Dumond avatar

      Cookies are pretty easy to crack from the client side, so I figured there must be something kind of hashing or encryption taking place. Thanks shola for looking into it.

      Lee Dumond — March 16, 2009 12:45 PM

    » Leave a Comment