Snowing Code

Personal notes on software development

Using ASP.NET MVC dynamic SiteMap to simplify User/Role authentication

(Publish date: 25/12/2009)

On of the security requirements of the app I’m working on is to let the admin user decide who can access what page. This is a fairly straight forward and rather frequent requirement, which most developers confront.

Now, since we’re working on an ASP.NET MVC project I had to have a look for an MVC SiteMapProvider, and came across this great work by Maarten Balliauw.

What we’ve done was overriding his Provider with a SQL-based one, to make it dynamic and more configurable. First and foremost, we’ve based our security model on a Role (or UserGroup if you prefer) with N Permissions (which translates to a Roles-Permissions many-to-many table). As soon as you establish this relation, when writing your SqlSiteMapProvider, in your BuildSiteMap() method you simply load only the current user Role Permissions property:

IList<Permission> permissions = _authenticationService.GetCurrentUserPermissions(userId);

And then you build your SiteMap graph with all the actions/operations/views the current user is permitted to access. Each Permission object has an Action and a Controller properties, and Maarten’s MvcSiteMapNode takes care of the Url property, using the Action and Controller properties. The Permission would also have a ParentPermission and ChildPermissions (in which case you’d only have to load all orphan- first level- permissions of current user role and eagerly fetch the child permissions bag property). On top of that, the permission Id property could work for the SiteMapNode Key.

What you’ve got now is a dynamic site map constructed according to the current user role/permissions. How do you use it then to know if the user is authorised to access a certain View? Quite simply, in your CustomBaseController, overriding the OnActionExecuting method you add:

if (SiteMap.Provider.CurrentNode == null) throw new AuthenticationException();

That simple :)

blog comments powered by Disqus