Thursday, May 6, 2010

How to use elevated priviledge in Sharepoint/how to Impersonate a user in the code.

There are actually many ways to acieve that, I am going to explain two of them here.


1. Using RunWithElevatedPrivileges of SPSecurity class.

The SPSecurity class provides a method (RunWithElevatedPrivileges) that allows you to run a subset of code in the context of an account with higher privileges than the current user.

The premise is that you wrap the RunWithElevatedPrivileges method around your code. And also In certain circumstances, such as when working with Web forms, you may also need to set the AllowSafeUpdates method to true to temporarily turn off security validation within your code. If you use this technique, it is imperative that you set the AllowSafeUpdates method back to false to avoid any potential security risks.



//Using RunWithElevatedPrivileges. code written in this section will run with higher priviledges
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = SPContext.Current.Site)
{
using (SPWeb web = site.OpenWeb(myWeb.ID))
{
web.AllowUnsafeUpdates = true;
//Write the code here to do the operation.
web.AllowUnsafeUpdates = false;

}
}
}

Another way to use this method is , define a public method that acts simply as a front end to the method that does the "real" work.

public void ProcessMethod()
{
SPSecurity.CodeToRunElevated elevatedMethod = new SPSecurity.CodeToRunElevated( ProcessMethodAsElevated);
SPSecurity.RunWithElevatedPrivileges(elevatedMethod);
}

The code uses a method from SPSecurity to indicate the name of the method that will run with Full Control(Basically using Application Pool Account).
In the first line, simply pass in the name of the method as the parameter. In the second line, you execute that method with elevated privileges.

Now create the method that does the real work. It is called by the first method (delegate), but executes with Full Control(under Application Pool Account):
private void ProcessMethodAsElevated()
{

//code goes here to do our work

}


2. Using windows impersonation.

Using this you want to run some code under the context of another user, you will need to hook into advapi32.dll library. following libraries are to be included

using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;


Then you need to declare an external reference at class level.

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static public extern bool LogonUser(string userName, string domain, string password, int logonType, int logonProvider, ref IntPtr accessToken);


using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using System.Data.SqlClient;

class TestClass
{

private const int LOGON_TYPE_INTERACTIVE = 2;
private const int LOGON_TYPE_PROVIDER_DEFAULT = 0;

[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static public extern bool LogonUser(string userName, string domain, string password, int logonType, int logonProvider, ref IntPtr accessToken);
static void ImpersonationCode()
{
IntPtr accessToken = IntPtr.Zero;
if (LogonUser("userName", "domain", "password", LOGON_TYPE_INTERACTIVE, LOGON_TYPE_PROVIDER_DEFAULT, ref accessToken))
{
using (WindowsIdentity identity = new WindowsIdentity(accessToken))
{
using (WindowsImpersonationContext context = identity.Impersonate())
{
// ... Write your code to implement logic here
context.Undo();
}
}
}

}

Now there is very important point, if you are doing any operation like adding a new item into library, it will leave the signature of system account and not the logged in current user. Now you may want to run the code in elevated priviledge but want to keep signature of current logged in user....coming in my next post.

Sanjay Tiwari
Dallas, Texas

No comments: