Drydo's Blog

Teenager of the Internet

This blog hosted by:
http://blogs.vbcity.com
  Home :: Syndication  :: Login   Community Forums   :: vbCity.com   :: DevCity.NET  

I love starting new projects with a new technology and recently the requirement for an ASP.NET 2.0 custom reporting module landed on my desk. I have some ASP.NET 1.1 experience having created a couple of sites about two years ago but that was it.

Keen to implement some of ASP.NET 2.0's cool features I came across the Membership, Roles and Profiles features @ http://www.4guysfromrolla.com and was impressed by how easy it was to generate a robust authentication system from scratch utilising Roles and various other niceities. However, out of all these articles there didn't seem to be anything that covered the scenario where the developer had already got a database and structure for storage and a library that could handle the authentication, role assignment and various other tasks.

Digging a little deeper it seemed that I could still utilise the login control then capture the 'authenticate' event and then employ my custom logic to authenticate the user. However, I wanted an easy way to identify whether the user was part of a specific role or not.

Now I must admit I checked out creating my own custom 'Role Provider' and whilst this might have been a better approach (especially if I wanted to expose routines to Add, Remove, Amend roles from a user) in the scenario where I'm handling this elsewhere - it seemed to be overkill.

Anyhoo, here's how I did it...

In my 'Authenticate' event of the login control I instantiate my custom authentication class. In my case, this class exposes a method to authenticate the user (returning a boolean value) and a property exposing the role of the user (which is a numerical value).

Note: it is possible of utilise multiple roles, my scenario precluded that option...

Here's the psuedo-code....

' Custom authentication class
Dim myAuthentication As New UserAuthentication
' Call custom authentication routine (where: conLogin is the Login control)
' and pass the username and password over

If
myAuthentication.AuthenticateUser(conLogin.UserName, conLogin.Password) Then
' If sucessful, generate the authentication ticket
Dim
ticket As New FormsAuthenticationTicket( _
1, _
"userName"
, _
DateTime.Now, _
DateTime.Now.AddMinutes(20), _
False
, _
myAuthentication.RoleId, _ ' Retreive the RoleId from the authentication class
FormsAuthentication.FormsCookiePath)
' Encrypt
Dim
encTicket As String = FormsAuthentication.Encrypt(ticket)
Dim
authCookie As New HttpCookie(FormsAuthentication.FormsCookieName, encTicket)
' Add to the cookies
Response.Cookies.Add(authCookie)
' Perform any appropriate navigation from the login page
Response.Redirect("NextPage.aspx")
End If

As you can see when I instantiate my AuthenticationTicket I pass the RoleId into the 'userData' argument. Once in there, I can now utilise that value elsewhere, namely the HttpApplication.AuthenticateRequest event where I can parse the current FormsIdentity, obtain the appropriate RoleId from the 'userData' property and add that to the 'roles' for the current user.

So, if you haven't created a Global.asax file, do so. Within here you need to capture the 'AuthenticateRequest' event of the Application object and then utilise the following code...

Protected Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As System.EventArgs)
' Does the object exist and is the user instantiate?
If
(((Not HttpContext.Current.User Is Nothing) AndAlso HttpContext.Current.User.Identity.IsAuthenticated) AndAlso TypeOf HttpContext.Current.User.Identity Is FormsIdentity) Then
' Retreive the current identity
Dim
id As FormsIdentity = CType(HttpContext.Current.User.Identity, FormsIdentity)
' Reset the User object and incorporate the new roles

HttpContext.Current.User = New System.Security.Principal.GenericPrincipal(id, New String() {id.Ticket.UserData})
End If
End Sub

So the User object is reset with the appropriate role. Note: that the 'roles()' argument of instantiation of 'GenericPrincipal' object does accept an array of string to support multiple roles.

Now, it is possible to utilise the base 'User.IsInRole' method and pass the appropriate RoleId over. However, I tend to make my job slightly easier by employing an Enum and utilising that, e.g.

If User.IsInRole(Constants.UserRoles.Administrator) Then
Response.Write("You're an Administrator!")
Else
Response.Write("You're a nobody.")
End If

And that's it. One block of code in the Global.asasx and one Enum to make coding slightly easily (admittedly without Option Strict On) and everything is up and running!

HTH - M

posted on Wednesday, September 19, 2007 11:18 AM

Feedback

# re: ASP.NET 2.0, Custom Role assignment without a 'Role Provider' 5/14/2008 8:05 PM dmitry39
thx it's a good solution

Regards from Russia

Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: