Monday, July 12, 2010

ASP.NET MVC2 and the Enterprise Library Security Block Authorization Provider

When I first started with ASP.NET 2.0 I was intrigued by the built-in support for users and roles via the Membership Providers. Unfortunately I quickly found limitations for its use mainly due to the way that I like to structure permissions in my applications.

I overcame some of these limitations by using the Enterprise Library Security block which allowed me to set granular permissions and then roll them up into groups of permissions which map to individual roles.

I recently switched over from ASP.NET, using the MVP pattern, to ASP.NET MVC2 and again found the the way roles are mapped to be too limiting. Therefore I decided to implement my own custom AuthorizeAttribute to check for specific authorization rules using the Enterprise Library Security block.

This article assumes that you know how to use Membership and Role providers in ASP.NET and that we have a role called Administrators already configured. If you aren't familiar with these I'd suggest looking at the following article:

Examining ASP.NET's Membership, Roles, and Profile

I also assume that you know how to use the MVC2 authorization model.

The first thing to do is add a reference to the following assemblies in your MVC project:

Microsoft.Practices.EnterpriseLibrary.Security
Microsoft.Practices.EnterpriseLibrary.Security.Configuration
Microsoft.Practices.EnterpriseLibrary.Common

Next we'll have to configure the security block in the web.config. I'm also going to create a authorization rule which maps a "Can Manage Users" permission into the Administrators role.
<configuration>
<configSections>
<section name="securityConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Configuration.SecuritySettings, Microsoft.Practices.EnterpriseLibrary.Security, Version=4.1.0.0" />
...
</configSections>
<securityConfiguration defaultAuthorizationInstance="RuleProvider" defaultSecurityCacheInstance="">
<authorizationProviders>
<add type="Microsoft.Practices.EnterpriseLibrary.Security.AuthorizationRuleProvider, Microsoft.Practices.EnterpriseLibrary.Security" name="RuleProvider">
<rules>
<add expression="R:Administrators" name="Can See Admin Menu" />
</rules>
</add>
</authorizationProviders>
</securityConfiguration>

Next we have to create our custom AuthorizeAttribute. This will allow us to check against the Enterprise Library Security block. We can do this by inheriting from the standard AuthorizeAttribute and overriding the AuthorizeCore method.
  public class AuthorizeRule : AuthorizeAttribute
{
public string Rule { get; set; }

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (string.IsNullOrEmpty(Rule))
{
throw new InvalidOperationException("Rule not specified");
}

if (!httpContext.User.Identity.IsAuthenticated)
{
return false;
}

IAuthorizationProvider auth = AuthorizationFactory.GetAuthorizationProvider();
return auth.Authorize(httpContext.User, Rule);
}
}

Finally we mark up the appropriate controller method that you want to secure just as we would using the AuthorizeAttribute.
[AuthorizeRule(Rule = "Can Manage Users")]
public void Index()
{
...
}

It's as easy as that.

Friday, July 2, 2010

When should software be rewritten

Over the last 14 years of my professional software development career, I have often heard developers complain about their existing code-base (including me). These complaints are generally along the same themes; how it has become difficult to maintain; that the code has become a big ball of mud; that changing code causes ripple effects; that no-one likes to touch module X because its so brittle; it takes new developers a long time to get up to speed with the code etc etc.

Normally the team consensus is that the product should be rewritten from the ground up. The idea is that this will sort out all of the design issues that are in the current version, it'll be more maintainable & more stable.

So the team embarks on this quest all the while management still wants new features and bug fixes to the existing version. This causes the original code-base to become a moving target causing the rewrite to take longer. This also ties up resources that could be working on new features, moving the product forward and adding value to the business.

In my experience the only time to rewrite a code-base is when moving to a new platform or technology. For example moving from Winforms to WPF. A rewrite is normally a lengthy and costly affair which rarely ends up with the clean design that was sought. New bugs are introduced which aren't covered by existing regression tests.

Rather than rewriting the entire application, the strategy I would recommend is to refactor it.

To get the most benefit from refactoring a code base, you'll need to increase testability. This will involve moving to a more loosely coupled design. I've chosen to use Behaviour Driven Design (BDD) which is an extension of Test Driven Design (TDD). Though you could bolt on tests after code but I wouldn't recommend that for many reasons which I won't go into here.

I have found that provided your code is loosely coupled and designed for testability, you are able to move towards an incremental design model in which developers can feel confident making changes and with greater speed.

So what happens if you have a tightly coupled application which might be tested by a QA team but doesn't have any unit tests?

Over the next few articles I'll be outlining some strategies for refactoring your legacy ASP.NET apps