1

在两种方法中,哪一种更适合以提升的权限运行?

第一种方法:

SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite curSite = new SPSite(SPContext.Current.Site.ID))
                    {
                        using (SPWeb web = curSite.OpenWeb(SPContext.Current.Web.ID))
                        {
                            try
                            {
                                web.AllowUnsafeUpdates = true;
                                \\ do your stuff
                            }
                            catch (Exception e)
                            {

                            }
                            finally
                            {
                                web.AllowUnsafeUpdates = false;
                                web.Dispose();
                            }
                        }
                    }
                });

第二种方法:

SPSite oSite = SPContext.Current.Site;
SPWeb oWeb = SPContext.Current.Web;
SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    using (SPSite curSite = new SPSite(oSite.ID))
                    {
                        using (SPWeb web = curSite.OpenWeb(oWeb.ID))
                        {
                            try
                            {
                                web.AllowUnsafeUpdates = true;
                                \\ do your stuff
                            }
                            catch (Exception e)
                            {

                            }
                            finally
                            {
                                web.AllowUnsafeUpdates = false;
                                web.Dispose();
                                oWeb.Dispose();
                                oSite.Dispose();
                            }
                        }
                    }
                });

他们中是否有人怀疑抛出“正在更新的网络已被外部进程更改”异常?

4

2 回答 2

6

首先,您应该调用SPWeb.ValidateFormDigest()SPUtility.ValidateFormDigest() 在提升代码之前调用。这将摆脱 GET 请求不允许的不安全更新,并避免您设置 AllowUnsafeUpdate 属性。

其次,正如 Nigel Whatling 所提到的,您正在第二个代码中处理上下文对象。您不必处理它们。简单来说,只处置您自己实例化的对象。像您这样的代码可能会导致副作用,因为其他 SharePoint 组件可能需要访问 SPContext.Current.XX 对象。这可能是您问题的根源。

第三,当您使用 using 构造时,您不必在 using 标头中设置的变量上调用 .Dispose() 。实际上, using 构造的作用(和实际好处)是您不必关心处置对象。一旦块代码退出,即使出现异常,也会在您的对象上调用 .Dispose() 方法。

总而言之,您的代码应更改为:

SPUtility.ValidateFormDigest();
SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (SPSite curSite = new SPSite(SPContext.Current.Site.ID))
    {
        using (SPWeb web = curSite.OpenWeb(SPContext.Current.Web.ID))
        {
              // Do stuff here
        }
    }
});

附注:要提升代码,您有两个选择。您在此处使用(调用SPSecurity.RunWithElevatedPrivileges)或使用 SystemAccount 令牌实例化新 SPSite 的那个:

using (SPSite curSite = new SPSite(
    SPContext.Current.Site.ID, 
    SPContext.Current.Site.SystemAccount.UserToken
))
{
    using (SPWeb web = curSite.OpenWeb(SPContext.Current.Web.ID))
    {
          // Do stuff here
    }
}

这将允许您在 Web 应用程序之外运行提升的代码。

您还应该考虑使用一些实用程序代码以更实用的方式包装此类操作。我习惯使用这样的代码:

public static void RunWithElevatedPrivileges(this SPWeb web, Action<SPSite, SPWeb> codeToRunElevated)
{
    if (CheckIfElevated(web))
    {
        codeToRunElevated(web.Site, web);
    }
    else
    {
        using (var elevatedSite = new SPSite(web.Site.ID, web.AllUsers["SHAREPOINT\\system"].UserToken))
        {
            using (var elevatedWeb = elevatedSite.OpenWeb(web.ID))
            {
                codeToRunElevated(elevatedSite, elevatedWeb);
            }
        }
    }
}

/// <summary>
/// Indicates whether the context has been elevated
/// </summary>
public static bool CheckIfElevated(SPWeb web)
{
    return web.CurrentUser.LoginName == "SHAREPOINT\\system";
}

使用这样的代码,您可以在代码中的某处简单地做:

SPContext.Current.Web.RunWithElevatedPrivileges((elevatedSite, elevatedWeb)=>{
     // do something will all privileges
});
于 2012-07-24T12:16:01.707 回答
1

两种方法几乎完全相同。除了在第二种方法中,您还要处理当前上下文的 SPWeb 和 SPSite 对象——这是您不应该做的事情。web.Update() 调用是否会引发异常?问题是在“做你的东西”代码中的某个地方吗?

于 2012-07-24T11:37:38.633 回答