ASP.NET Security Basics: Caching Roles

Just a quick "request" post covering the basics of caching user roles in an ASP.NET application using forms based authentication.

Role based authentication & authorisation is an important part of most modern web applications.  After successful authentication of a user, an authorisation process must take place to determine which areas of the application the user has access to.

To implement the basic role based security, there are three points to be considered. In this example we are returning a list of roles from a database for a particular user.

We can then add a web.config to each directory we wish to protect in the following format.

<authorization>
 <allow roles="role1,role2"></allow>
<deny users="*"></deny> </authorization>

Application_AuthenticateRequest is defined in Global.asax and will be accessed each time a web request is made if your application. In order to save a database trip for each time you're grabbing your roles, it's best to use a cached mechanism for this:

   Try
            If HttpContext.Current.User IsNot Nothing Then
                If HttpContext.Current.User.Identity.IsAuthenticated Then

                    If HttpContext.Current.User.Identity.AuthenticationType <> "Forms" Then
                        Throw New Exception(String.Format("You attempted to authenticate with {0} but only forms authentication is accepted.", HttpContext.Current.User.Identity.AuthenticationType)
                    End If

                    Dim userId As System.Security.Principal.IIdentity = HttpContext.Current.User.Identity

                    ' If the roles aren't in cache, do it now.
                    If System.Web.HttpContext.Current.Cache(userId.Name) Is Nothing Then

			
			' Just a simple example using a dataset!

                        Dim dsRoles As DataSet = SomeStaticClass.GetRoles(User.Identity.Name) ' Get roles as a comma delimited string

                        Dim roles As String() = New String(dsRoles.Tables(0).Rows.Count - 1) {}
                        For row As Integer = 0 To dsRoles.Tables(0).Rows.Count - 1

                            For col As Integer = 0 To dsRoles.Tables(0).Columns.Count - 1
                                roles(row) = dsRoles.Tables(0).Rows(row)(col).ToString()
                            Next
                        Next

                        ' Usually this information will be collected from a database.           
                        ' One hour expiration time
                        System.Web.HttpContext.Current.Cache.Add(userId.Name, roles, Nothing, DateTime.MaxValue, TimeSpan.FromHours(1), System.Web.Caching.CacheItemPriority.BelowNormal, _
                         Nothing)

                    End If

                    'Assign the roles to the user in the current security context
                    HttpContext.Current.User = New System.Security.Principal.GenericPrincipal(userId, DirectCast(System.Web.HttpContext.Current.Cache(userId.Name), String()))

                End If
            End If
        Catch ex As Exception
            Response.Redirect("/MyErrorPage")
        End Try
I'm running the 39th BMW Berlin Marathon on 30th September 2012 for the British Lung Foundation, who are currently funding research on the prevention of lung damage in COPD and many other areas related to lung disease.

I'm participating with my sister Claire Kewney and, on behalf of the charity, would appreciate even the smallest donation. My own JustGiving page is here, our team page is here.

if you're in the UK, you can also donate using your mobile phone by texting NKEW82 £5 (or any amount) to 70070. Your donation will be appreciated!

Comments

Your Comment
Your Name
E-mail Address (This won't be published)
Website URL

You can manage your Kewney.com account by logging in. [ Log On ]