views:

111

answers:

4

Hi! I need to organize some simple security in a class depends on value of the enum. All that I can figure out is using attribute on a method and then run check then if it fails throw an exception. Sample:

    [ModulePermission(PermissonFlags.Create)]
    public void CreateNew()
    {
        CheckPermission();
        System.Windows.Forms.MessageBox.Show("Created!");
    }
    protected void CheckPermission()
    {
        var method = new System.Diagnostics.StackTrace().GetFrame(1).GetMethod();
        if (!flags.HasFlag(method.GetCustomAttributes(true).Cast<ModulePermissionAttribute>().First().Flags))
        {
            throw new ApplicationException("Access denied");
        }
    }

is there more elegant or simple way to do this, like just to trigger an event when method run?

A: 

You could take a look at Aspect Oriented Programming. Check out Postsharp for instance, which will enable you to 'weave' some additional logic at compile time in the methods that you've decorated with your ModulePermission attribute.

By doing so, you will not have to call the 'CheckPermission' method anymore inside that 'secured' method, since that logic can be weaved by Postsharp.

(A while ago, I've been playing around with Postsharp: http://fgheysels.blogspot.com/2008/08/locking-system-with-aspect-oriented.html )

Frederik Gheysels
A: 

You might want to look at doing this with something like PostSharp, which will give you a framework for applying the attributes so that you don't have to run the check in your method. This may, however, increase the complexity depending on how the currently active flags are accessed. You'd probably need some class to cache the current permissions for the current user.

tvanfosson
+6  A: 

Why not just use standard Code Access Security instead of reimplementing the attribute handling and stack walking?

I think that if you read through the linked documentation, you'll see that what you have is nowhere close to what is needed to achieve actual security. Thankfully, this hard problem has already been solved...

Nick Guerrera
+3  A: 

Not with an enum, but with strings - voila (enforced by the runtime, even in full-trust):

public static class PermissionFlags {
    public const string Create = "Create";
}

[PrincipalPermission(SecurityAction.Demand, Role = PermissionFlags.Create)]
public void CreateNew() {
    System.Windows.Forms.MessageBox.Show("Created!");
}

All you need to do now is to represent the user as a principal. This is done for you in ASP.NET, and there is a winform plugin (in VS2008 etc) to use ASP.NET for membership. It can be configured for vanilla winforms and WCF, too; at the most basic level, GenericPrincipal / GenericIdentity:

// during login...
string[] roles = { PermissionFlags.Create /* etc */ };
Thread.CurrentPrincipal = new GenericPrincipal(
    new GenericIdentity("Fred"), // user
        roles);

But you can write your own principal / identity models easily enough (deferred / cached access checks, for example).

Marc Gravell