SPSecurity.RunWithElevatedPrivileges - an important point while using it in web context

Normally we will use SPSecurity.RunWithElevatedPrivileges() to execute some code that has to be run under some higher privileges.

Whenever we use SPSecurity.RunWithElevatedPrivileges(), it will execute the code under the context of Application Pool identity. Now we can see a scenario where we will get the “Access denied” exception from the code block even if you use SPSecurity.RunWithElevatedPrivileges.

This was the code snippet that I have used initially inside a custom webpart to read XML content from of an InfoPath form which was uploaded in a document library. This code will throw an “Access denied” exception while calling the OpenBinaryStream() method whenever I execute it through an Anonymous user account.

SPSecurity.RunWithElevatedPrivileges(delegate()

 {

      SPWeb oWeb = SPContext.Current.Web;

      SPList oList = oWeb.Lists["InfoPathLib"];

      SPListItem oListItem = oList.Items[0];

      Stream oStream = oListItem.File.OpenBinaryStream();

      StreamReader oReader = new StreamReader(oStream);

      string strLine = "";

     

      strLine = oReader.ReadLine();

     

      oReader.Close();

      oStream.Close();

      oReader.Dispose();

      oStream.Dispose();

      lblFileContent.Text = strLine;

      this.Controls.Add(lblFileContent);

 });

Here the problem was, whenever we take the SPWeb instance using

SPWeb oWeb = SPContext.Current.Web;, then SPWeb instance still running under anonymous account only , because we are taking it through the current web context in which the current user is running under anonymous account (IUSR_MachineName). That was the reason that we got that “Access Denied” exception. We need to remember this point all time whenever we use RunWithElevatedPrivileges under the web context.

So what we need to that, we have to take the current context outside the SPSecurity.RunWithElevatedPrivileges block and then create a new instance of SPSite and SPWeb inside the that block which will run under application pool identity.

SPWeb oWeb1 = SPContext.Current.Web; // taking the current SPWeb context running under the anonymous account

SPSecurity.RunWithElevatedPrivileges(delegate()

{

using (SPSite oSite = new SPSite(oWeb1.Site.Url))

{

// creating a new SPSite running under Application pool idenity

using (SPWeb oWeb = oSite.OpenWeb())

{

SPList oList = oWeb.Lists["InfoPathLib"];

SPListItem oListItem = oList.Items[0];

Stream oStream = oListItem.File.OpenBinaryStream();

StreamReader oReader = new StreamReader(oStream);

string strLine = "";

strLine = oReader.ReadLine();

oReader.Close();

oStream.Close();

oReader.Dispose();

oStream.Dispose();

lblFileContent.Text = strLine;

this.Controls.Add(lblFileContent);

}

}

});

The above code will work fine and we can read the InfoPath document. So, please do not forget to create a new instance of SPSite and SPWeb inside SPSecurity.RunWithElevatedPrivileges,while using it in a web context.

 

 

Another work-around to this paritcular requirement (read the file content) is - use GetFileAsString() method of the SPWeb directly. And here there is no need to use the SPSecurity.RunWithElevatedPrivileges. Since, I have enabled anonymous authentication on this SharePoint web application it will allow to read the file using the below method under the context of anonymous account.

string

strXML = SPContext.Current.Web.GetFileAsString("/FannyDocLib/Form1.xml");