Linq to SharePoint與權限提升

SharePoint 2010支持Linq to SharePoint,讓程序員可以使用Linq語法直接訪問SharePoint 2010網站中的數據。但是在默認情況下,Linq to SharePoint不支持權限提升,也就是說,如果在代碼中嘗試通過SPSecurity.RunWithElevatedPrivileges()方法來提升執行權限,你可能會發現,代碼並不會如你所願的以系統帳戶的身份,訪問SharePoint網站的數據。

下面是一段典型的權限提升的代碼,在匿名委託方法中,首先構造了新的SPSite和SPWeb對象,然後使用Linq to SharePoint查詢了一個列表中所有列表項的標題。雖然看起來Linq to SharePoint好像會被提升它執行的權限,但實際情況並非如此。在下面的代碼中,中間的Linq to SharePoint代碼並不會受到外面調用SPSecurity.RunWithElevatedPrivileges()方法的影響。

private IEnumerable<String> GetAllHardwareNames()
{
    var currentWebUrl = SPContext.Current.Web.Url;
    List<String> result = null;

    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        using (var site = new SPSite(currentWebUrl))
        {
            using (var web = site.OpenWeb())
            {

                using (var ctx = new ContosoDataContext(currentWebUrl))
                {
                    var names = from h in ctx.硬件資產跟蹤
                                select h.標題;
                    result = names.ToList();
                }
            }
        }
    });

    return result;
}

如果希望Linq to SharePoint代碼能夠提升它的執行權限,在使用Linq to SharePoint之前,需要做一個比較trick的事情,那就是將當前HttpContext對象設置爲null。下面的代碼中,使用粗體標識了這些特殊的代碼。

SPSecurity.RunWithElevatedPrivileges(delegate()
{
    using (var site = new SPSite(currentWebUrl))
    {
        using (var web = site.OpenWeb())
        {
            var httpContext = HttpContext.Current;
            HttpContext.Current = null;

            using (var ctx = new ContosoDataContext(currentWebUrl))
            {
                var names = from h in ctx.硬件資產跟蹤
                            select h.標題;
                result = names.ToList();
            }

            HttpContext.Current = httpContext;
        }
    }
});

只所以要使用這個技巧,是因爲在Linq to SharePoint的實現中,使用了一個名爲Microsoft.SharePoint.Linq.Provider.SPServerDataConnection的類,來真正連接到SharePoint網站。在這個類的構造函數中,有類似這樣的代碼:

if (SPContext.Current != null)
{
    this.defaultSite = SPContext.Current.Site;
    this.defaultWeb = (SPContext.Current.Web.Url == url) ? SPContext.Current.Web : this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
}
else
{
    this.defaultSite = new SPSite(url);
    this.defaultWeb = this.defaultSite.OpenWeb(new Uri(url).PathAndQuery);
}

爲了提高性能,它會優先重用SPContext對象中所緩存的SPWeb和SPSite對象。這個行爲雖然可以提高代碼的運行效率,但是卻會導致權限提升的失效,因爲提升了權限的代碼必須使用一個新構造的SPSite和SPWeb對象。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章