views:

76

answers:

5

I am familiar with impersonating an account in .net by using:

dim myIdentity as WindowsIdentity = someIdentity  
using ctx as WindowsImpersonationContext = myIdentity.Impersonate()  
    doStuff()  
end using

Is it possible to define a .net attribute so that I could write something like:

< runAsUser(someIdentity) > public sub doStuff()

and then have the .net framework always impersonate when running the method doStuff()?

Update Okay, I'm told that this may be impossible because arguments to an attribute constructor must be constants which would rule out passing in the user's identity.

Let me ask the question a little bit differently: Suppose there were a function getUserWindowsIdentity() that returns an identity associated with the logged in user.

Could I then use < runAsLoggedInUser) > public sub doStuff() > to make the framework always impersonate the user id returned by getUserWindowsIdentity when running the doStuff() method?

+2  A: 

No, such magic does not exist in the .NET framework. You'd have to write the code yourself, using Reflection to read the attribute. That code will look a lot like the code you already have, just slower and with the code to read the attribute added.

Hans Passant
I think he's not asking if it exists, but rather if it's *possible* to define such an attribute/tag to do so.
Daniel DiPaolo
Well, sure it is possible. But there's nothing in the framework or the compiler that will make the attribute do anything useful.
Hans Passant
+1  A: 

I'm fairly certain this can't be done. You might be able to simulate it with PostSharp (or similar.)

Parameters passed to Attribute constructors must be constants, meaning they can't be reference types at all. I would question the use case where a code block should always run under the same hard-coded credentials, as well.

Toby
Could the attribute class possibly be coded to look up the identity if it's easy to get without passing in ref arguments?
Rice Flour Cookies
Yes, but you would still have to have other code that processed the attribute and actually did something with it. As a general rule, attributes are used as markers that are reflected from other code. The code that called your method would need to load and process the attribute, and actually perform the impersonation. If you have multiple methods being called from the same location that each need to run under different, pre-defined credentials, then I can see some potential benefit.
Toby
A: 

I'm not expert, so I'll concede to the other answerers that you can't do this the way you've suggested, but you might be able to write code that looks the way you want it to and as fast as the code you've been using.

If you write in a preprocessor directive to replace the attribute tag with a using block, you'd pretty much get the best of both worlds. This could probably be achieved with a script that runs over your source code, as well.

Caleb Thompson
+1  A: 

If you control either: a) the code that invokes the doStuff() method or b) the means by which the caller of doStuff() gets a reference to the object / class on which doStuff() is implemented, then you can accomplish what you're looking for. Item b) is preferred.

If that's possible, look into dynamic proxies - http://www.castleproject.org/dynamicproxy/index.html. Instead of returning an actual instance of the object / class in question, return a proxy for the instance. When the caller invokes the method, the proxy sees it first. In the proxy's implementation, look for your attribute on the method that's being called and, if found, initiate the impersonation.

Donnie

soccerdad
+1  A: 

As others have answered, you can create an Attribute that will do "work", but what has not been explicitly stated is that there are no custom attributes that you can create that the run-time or framework components will execute on your behalf. So you can create an attribute such as:

public class RunAsUserAttribute : Attribute
{
    // implement some attribute functionality here
}

and you could then use that attribute on a method or class:

[RunAsUser]
public void DoStuff()
{
    // do some stuff as the impersonated user
} 

what component is going to invoke the functionality in the RunAsUserAttribute class? You could put this kind of functionality in a dynamic proxy as suggested by soccerdad. This is one way to solve the problem.

Cheers.

Dave White