Saturday, April 13, 2013

How to avoid the fatidic UnauthorizedAccessException (0×80070005)

Recently I came across a series of issues when a client I had worked with changed their security matrix.

I had a webpart that applied a CAML query on a list to retrieve data and then present it. The problem I was having, when the customer changed their security matrix, was that some users no longer had permissions to retrieve the list where the data was being stored.
(...)


While this seems to be a harmless permission level, in practice the page request would end up with an “Access Denied” error being thrown when the web part ran:



This error happens whenever a UnauthorizedAccessException is thrown by the processing thread. In the ULS logs, this shows up as the fatidic "<nativehr>0×80070005</nativehr><nativestack></nativestack>".
Also, this Exception usually terminates the thread where the code was being processed, so no ammount of try/catch blocks will help you to handle the exception.


However, data on this list could be sensible, so I did not wish to use the frequently used “SPSecurity.RunWithElevatedPrivileges()” method, which would allow for potentially sensitive data to be queried/displayed.


If you cannot use the RunWithElevatedPrivileges method, another way to accomplish a simple CAML query on a SPList is by telling SharePoint to temporarily ignore the Permission verifications.
You can accomplish this by using theSPSecurity.CatchAccessDeniedException property and the SPList.DoesUserHavePermissions method, like so:

SPList list = null;
bool oldValue = SPSecurity.CatchAccessDeniedException;
try
{
    if (oldValue != false) { SPSecurity.CatchAccessDeniedException = false; }
    //
    list = web.GetList(listUrl);
}
finally
{
    bool newValue = SPSecurity.CatchAccessDeniedException;
    if (oldValue != newValue) { SPSecurity.CatchAccessDeniedException = oldValue; }
}
//
if (list.DoesUserHavePermissions(SPBasePermissions.ViewListItems) == true)
{
    XElement xmlQuery = new XElement("Where",
        new XElement(compareOperation ?? "Eq",
            //new XElement("Value", new XAttribute("Type", fieldType ?? "Text"),
                new XElement("FieldRef", new XAttribute("Name", fieldInternalName)),
            //),
            new XElement("Value", new XAttribute("Type", fieldTypeAsString ?? "Text")) { Value = fieldValueAsString }
        )
    );
    SPQuery query = new SPQuery() { Query = xmlQuery.ToString(SaveOptions.DisableFormatting) };
    SPListItemCollection items = list.GetItems(query);
    try
    {
        if (items != null && items.Count > 0)
        {
            ret = items;
        }
        else { }
    }
    catch (SPException ex)
    {
        Logger.Error(ex, "Error in getListItems() after trying to return queried Items from '{0}'. CAML query is probably malformed. (camlQuery.Query:'{1}')", ((list != null) ? list.RootFolder.ServerRelativeUrl : "null"), query);
    }
}

No comments:

Post a Comment