views:

146

answers:

2

I have some methods that need to run as a certain service account, so I do the normal thing:

public DoSomeWorkAsServiceAccount() {
    ...
    // assume I am given tokenHandle
    WindowsIdentity newId = new WindowsIdentity(tokenHandle); 
    WindowsImpersonationContext impersonatedUser = newId.Impersonate();

    ...
    // do the work here
    ...

    impersonatedUser.Undo();
}

I'd like to avoid writing this code in every method, so I was thinking of creating a custom attribute:

[Impersonate(tokenHandle)]
public DoSomeWorkAsServiceAccount() {
    // do the work
}

So here are my questions:

  1. Is this possible?
  2. Can you show me something that will avoid code duplication?

Thanks in advance.

+3  A: 

Hi there.

I've don't have any code, but you could try using PostSharp to do this. You could create an OnMethodInvocationAspect which arranges the security stuff before calling the method code. eg

public class ImpersonateAttribute : OnMethodInvocationAspect
{
  public override void OnInvocation(MethodInvocationEventArgs eventArgs)
  {
    WindowsIdentity newId = new WindowsIdentity(tokenHandle); 
    WindowsImpersonationContext impersonatedUser = newId.Impersonate();

    eventArgs.Proceed() // Call the code in the actual method.

    impersonatedUser.Undo();
  }
}

The above is a complete guess, but by suggesting it, I may have given you a valid option.

Cheers. Jas.

Jason Evans
Thanks - I didn't realize that attributes were just data, and a framework was needed to make it "do stuff".
Jeff Meatball Yang
+2  A: 

I don't think an attribute is the best way to implement a feature like this. For the most part attributes merely act as meta-data on types and members (Aspect Oriented stuff aside). You'd need to write something to check for that attribute, and re-route the method call accordingly. If you already have some AOP code in place this shouldn't be much of a chore, but if you don't you'd likely be much better served by something like this:

public void DoWorkAsUser(tokenHandle, Action op)
{
  WindowsIdentity newId = new WindowsIdentity(tokenHandle); 
  WindowsImpersonationContext impersonatedUser = newId.Impersonate();

  op();

  impersonatedUser.Undo();
}

And then call it like this:

DoWorAsUser(token, MyMethod);

This allows you to centralize the impersonation code without having to mess around with reflection, codeweaving, etc.

akmad
Thanks for the answer... I wish we had AOP. And BTW, your icon is awesome.
Jeff Meatball Yang
You're welcome! I didn't put it in the example, but make sure you wrap your 'op' call in a try finally block and dispose the WindowsIdentity and WindowsImpersonationContext objects.
akmad