views:

99

answers:

1

I've got a web part that accesses the SP object model, packaged in an assembly which is signed and deployed to the GAC. The web.config is set for "Full" trust, and yet my web part throws a SecurityException. The offending lines of code:

SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(() =>
{
    foreach (SPGroup g in user.Groups)
    {
        identity += String.Format(",'{0}'", g.Name.ToLowerInvariant().Replace(@"\", @"\\"));
    }
}));

It appears that the exception is thrown when RunWithElevatedPrivileges is called (in other words, my delegate doesn't execute at all). Any ideas? I'm completely bewildered at this point.

update: here's what the code looked like before I wrapped it in the RunWithElevatedPrivileges method:

public MyWebPart()
{            
    context = new MyProject.Data.MyDataContext(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString);
    SPUser user = SPContext.Current.Web.CurrentUser;
    identity = String.Format("'{0}'", user.LoginName.ToLowerInvariant().Replace(@"\", @"\\"));
    foreach (SPGroup g in user.Groups)
    {
        identity += String.Format(",'{0}'", g.Name.ToLowerInvariant().Replace(@"\", @"\\"));
    }            

    identity = '[' + identity + ']';
}

And the exception:

System.Security.SecurityException occurred
  Message="Request failed."
  Source="Microsoft.SharePoint"
  StackTrace:
       at Microsoft.SharePoint.SPBaseCollection.System.Collections.IEnumerable.GetEnumerator()
       at MyProject.MyWebPart..ctor()
  InnerException: 

Based on the highlight provided by the exception helper, it looks like the attempted access of the SPUser.Groups property is the problem: user.Groups.

What's got me really confused is that this exact code was working fine two days ago, but I had some other problems with the farm and basically had to rebuild it. After getting everything else back up again, I went and tried to add this web part to a page and this problem manifested itself. I tried wrapping the code in the RunWithElevatedPrivileges wrapper to see if I could isolate exactly the offending bit, but it looks like anything that touches the SP oject model causes the exception, including the RunWithElevatedPrivileges method.

update2: I still don't know the real reason this was failing, but it was happening when I was trying to add the web part. After setting breakpoints in the debugger, I realized that the constructor was being called twice; the first time, it all worked exactly as expected, but the second time was when the exception was being thrown. I still have no idea why. I found two ways around this: move the offending code out of the constructor into a later point in the lifecycle of the web part, or comment out the code to add the web part, then uncomment it and redeploy.

Apparently, the reason this "worked 3 days ago" was because I had added my web part to a page a long time ago, and then added the above code to the constructor. Since the web part was already added, I never saw any problems. Later, when I recently had to rebuild the site and add the web part to the page again, this problem manifested itself. So technically, it didn't "work" before, I just wasn't doing the thing that made it misbehave.

Anyway, like I said - I still don't know the true cause of the exception, so answers along those lines are still welcome.

+1  A: 

The problem could occur if you try to work with SharePoint objects which were created outside of the RunWithElevatedPrivileges() method, and therefore still hold their old security context. In your case you use a SPUser object which was not created within the RunWithElevatedPrivileges() method.

To work around, you should create the object you want to work with within the delegate. Safe Ids or URLs outside of the delegate, to use them for recreating the objects. E.g.: safe the URL or ID of a SPSite object and use it to create it again within the delegate.

 public void Demo()
 {
      string  siteURL = SPContext.Current.Site.Url;
      SPSecurity.RunWithElevatedPrivileges(delegate(){

          using (SPSite safeSite = new SPSite(siteURL))
          {
             // place your code here ... 
          }
      });
  }

Perhaps you could post the stack trace so we can get some more information.

Flo
updated the OP.
Ben Collins