If you've gotten this far, you've seen both how to share an impersonated identity with worker threads, and you've seen an example that demonstrates it works. But in case you just skipped here or got lost in the midst of it all, here are the steps you need to take:
-
Set up your application to run under a specific identity in IIS.
-
Add the <identity impersonate="true" /> element to the system.web section of your Web.config (or Machine.config) file.
-
Create a static/Shared member of type System.Security.Principal.WindowsIdentity.
-
Set that shared member to be the identity of your main application threads.
-
Do some asynchronous calling using ThreadPool.QueueUserWorkItem.
-
In your worker thread method(s), create a new WindowsPrincipal using the shared identity from Step 3.
-
Set the current thread's principal to that principal.
-
Call Impersonate on the shared identity.
-
Do your work using that identity.
-
Call Undo on your impersonation context.
That's it. In ten, relatively easy steps, you can ensure that all of your application's code is running under the same identity configured by you (or your hosting provider).
In fact, to make your life easier, I've created a reusable class that you can plug into your application. This class cuts out steps 3, 4, 6, and 7--nearly half. All you need to do is download (includes C# and VB.NET version) the code and either drop the (language-appropriate) file into your project or copy and paste the class into your Global class. If you do the latter, you can then simply call like below.
System.Security.Principal.WindowsImpersonationContext wi = Global.Impersonation.Impersonate();
// do some stuff
wi.Undo()
Again, calling Undo is optional, but it is recommended. If you look at the class, it you will note that I get around step 4 (above) by creating a static property that will get the current thread's identity. It is virtually guaranteed this will work as long as the first thread to call Impersonate is running under the desired identity, which should be the case most of the time. If you want to be 100% sure, you can always still just set that property to the identity that you want prior to calling Impersonate.
Please note this article came out of a real need caused by just this situation with dasBlog and my hosting provider. If you're curious, you can read about that on my blog. Also note that I translated the impersonation helper class using Alex Lowe's translator. It worked like a charm except it didn't understand my in-class #region statements. It also didn't handle my delegate instantiation in my test code--I had to change it to use AddressOf Me.DoSomething, but it still saved me a lot of time!