Since I’ve been ranting on this for a few days, I thought I’d wrap it up. When SPSecurity was first found, we thought it was the best thing in the API since since SPPeanutButter. We used it… we abused it… we loved it. Over the course of the last few months though, it betrayed us. We started to see all sorts of obscure bugs when working with the SharePoint object model within the delegate in RunWithElevatedPrivelege. One such issue was with My Sites. Somehow, we managed to abuse SPSecurity.RunWithElevatedPrivilege enough to disable MySite creation in the current ASP.NET application in completely unrelated code. Through simple calls sent through RunWithElevatedPrivilege we were able to corrupt the ASP.NET application instance so that MySites could not be created, with another misleading error message on the failed My Site creation page. QA loved this, of course.
As the MSDN documentation says, SPSecurity.RunWithElevatedPrivelege "Executes the specified method with Full Control rights even if the user does not otherwise have Full Control." What it does is it uses the Win32 ImpersonateSelf API method to drop down to the thread’s identity. There’s a lot of hairy native code that’s used to do this… just check out the method with Reflector. What we found was that all SP object model instances need to be created and disposed of inside of the delegate– and even that can cause obscure bugs.
I’m not recommending to never use SPSecurity– but I will recommend to never use SPSecurity to access or manipulate the SharePoint object model. There’s too much overhead, too much chances of introducing obscure bugs, and too much potential abuse. Only us SPSecurity.RunWithElevatedPrivelege to use the application pool’s credentials for network calls. And for that, you may be better off simply using WindowsImpersonationContext and WindowsIdentity.Impersonate(IntPtr.Zero).
For all other impersonation needs, use the SPUserToken to impersonate. Remember that the elevation of the object model happens through the SPSite constructor- no matter which elevation method you use, either through RunWithElevatedPrivilege or though simple impersonation using the user token.
To impersonate the SYSTEM and use elevated privilege, get the user token from the SYSTEM ACCOUNT. Fortunately, the SystemAccount SPUser is a property of any SPSite object. So instead of using SPSecurity.RunWithElevatedPrivelege, you can use the following code to perform elevated actions:
SPUserToken sysToken = SPContext.Current.Site.SystemAccount.UserToken;
using(var systemSite = new SPSite(SPContext.Current.Site.ID, sysToken))
using (var sysWeb = systemSite.OpenWeb(SPContext.Current.Web.ID))
// Perform elevated actions here