Elevated Privileges

From SharePoint Knowledge Base

Jump to: navigation, search

Often it is useful to write code which has the ability to perform tasks that the user executing the code cannot do. For example, you may want to capture feedback from a user through a custom web part and add that feedback to a SharePoint list that the user does not have access to directly. Since server-side code executes in the context of the current user, the attempt to write the list item would fail.

The way around this is to use a method on SPSecurity called RunWithElevatedPrivileges. This method accepts an anonymous delegate which will contain all of the code you want to execute. Any code within this delegate will execute as the system account.

Contents

Example

This snippet of code shows the use of RunWithElevatedPrivileges in context.

// this code runs in the context of the user
SPWeb web = SPContext.Current.Site.RootWeb;
SPList list = web.Lists["My List"];

// this code will run in the context of the system account
SPSecurity.RunWithElevatedPrivileges(delegate()
{
   SPSite rootSite = new SPSite("http://myserver");
   SPWeb rootWeb = rootSite.RootWeb;
   SPList myList = rootWeb.Lists["My List"];
});

// now we're back to the user context
int itemCount = list.ItemCount;

One important thing to note is that only objects instantiated within the RunWithElevatedPrivileges code block will have the context of the system account. So objects created outside of that will still have the context of the current user - even if they are used within the RunWithElevatedPrivileges block.

// create an object in the context of the user
SPWeb web = SPContext.Current.Web;

// run as system account
SPSecurity.RunWithElevatedPrivileges(delegate()
{
   // this will execute as the current user, not the
   // system account because it is accessing the web
   // object which was instantiated outside of the 
   // RunWithElevatedPrivileges block
   SPList myList = web.Lists["My List"];
});


Gotchas

Event Receivers

RunWithElevatedPrivileges is often used in Event Receivers to perform some sort of automation. Event receiver methods are passed SPItemEventProperties objects which provide easy access to the current list, current list item, current web, etc. However, you cannot use these objects directly within a RunWithElevatedPrivileges block because they were instantiated outside in the context of the user. As a workaround, you can re-create these objects within the context of the system account.

public override void ItemAdded(SPItemEventProperties properties)
{
   // start sys account context
   SPSecurity.RunWithElevatedPrivileges(delegate()
   {
      // accessing the list item directly from the properties
      // will execute as the end user - not the system account
      properties.ListItem["Title"] = "Hello";

      // instead, re-instantiate these objects using data from the
      // properties, but not the actual objects themselves
      SPSite site = new SPSite(properties.SiteId);
      SPWeb web = site.OpenWeb(properties.RelativeWebUrl);
      SPList list = web.Lists[properties.ListId];
      SPListItem item = list.Items.GetItemById(properties.ListItemId);
      item["Title"] = "Hello";

      item.Update();
   }
}

Created By / Last Modified By

When making changes to a list item as the System Account, the Last Modified By or Created By information will show up as "System Account". This is because that code is actually executing as that system account - not the end user.


Code Access Security

If you use this in code that is not fully trusted you must add the Impersonate="true" attribute to the SharePointPermission IPermission node in your CodeAccessSecurity section.

Here's an example:

<IPermission 
    class="Microsoft.SharePoint.Security.SharePointPermission, 
           Microsoft.SharePoint.Security, 
           Version=12.0.0.0, 
           Culture=neutral, 
           PublicKeyToken=71e9bce111e9429c" 
    ObjectModel="True" 
    version="1" 
    Impersonate="true" />

In addition, if you need to set the AllowUnsafeUpdates property to true, you will have to add the UnsafeSaveOnGet attribute to "true".

Here is a sample CodeAccessSecurity block setting everything you should need.

<CodeAccessSecurity> 
  <PolicyItem> 
    <PermissionSet class="NamedPermissionSet" version="1" Description="Permission set for My Assembly"> 
      <IPermission class="AspNetHostingPermission" version="1" Level="Minimal" /> 
      <IPermission class="SecurityPermission" version="1" Flags="Execution" /> 
      <IPermission class="Microsoft.SharePoint.Security.SharePointPermission, 
                          Microsoft.SharePoint.Security, 
                          Version=12.0.0.0, 
                          Culture=neutral, 
                          PublicKeyToken=71e9bce111e9429c" 
                   version="1" 
                   ObjectModel="True" 
                   Impersonate="True" 
                   UnsafeSaveOnGet="True" /> 
    </PermissionSet> 
    <Assemblies> 
      <Assembly Name="My.Assembly" /> 
    </Assemblies> 
  </PolicyItem> 
</CodeAccessSecurity>

AllowUnsafeUpdates

When using this in a web part or user control you must set the AllowUnsafeUpdates property to true. If you don't you will get the error message "The security validation for this page is invalid".

SPSecurity.RunWithElevatedPrivileges(delegate()
{
   SPSite site = new SPSite(SPContext.Current.Site.Url);
   SPWeb web = site.RootWeb;
   
   web.AllowUnsafeUpdates = true;
   
   ...
});
Personal tools