Sharepoint Security and .NET Impersonation
Для использования имперсонализации для всякого рода нужд в рамках SharePoint-а необходимо знать некоторые, не совсем очевидные, хитрости.
Хозяйке на заметку:
Impersonation is the ability of a thread to execute in a security context that is different from the context of the process that owns the thread.
Все дальнейшие выкладки основаны на совместных поисках истин с тов. WSA, здравом смысле и некоторых источниках (см. ниже). Процесс имперсонализации под SharePoint включает в себя следующие этапы.
- Имперсонализация для текущего потока под нужной учётной записью.
- Создание объектов
SPSiteиSPWeb. - Выставление
AllowUnsafeUpdatesдля данных объектов вtrue. - И непосредственно совершение необходимых нам манипуляций
И так пройдёмся слегка по первым пунктам.
1. Имперсонализация для текущего потока под нужной учётной записью
Здесь возможны 2-ва варианта:
- залогинивание под определённым пользователем (для этого необходимо знать, и соответственно где-то хранить пароль)
- application identity
Залогиненивание под определённым пользователем имеет довольно большой недостаток — необходимо где-то хранить пароль.
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
Второй вариант это имперсонализация под application identity. Данный способ видится наиболее лучшим вариантом, ибо не обеспечивает необходимый уровень привилегий, плюс нет надобности хранить где-либо пароль.
System.Web.Hosting.HostingEnvironment.Impersonate()
Хозяйке на заметку:
Note: This method is new in the .NET Framework version 2.0.
2. Создание объектов SPSite и SPWeb.
Объектная модель SharePoint-а такова, что даже если мы имперсонализировалиcь под другой учётной записью, то это ни разу не значит что
SPContext.Current.Site
уже знает о наших текущих привилегиях. Посему необходимо создать новый объекты
SPSite и SPWeb и уже работать с ними.
SPSite site = new SPSite(SPContext.Current.Site.Url);
SPWeb web = site.OpenWeb(SPContext.Current.Web.ServerRelativeUrl);
Хозяйке на заметку:
Не забываем что данные объекты реализуютIDisposable.
Далее ИМХМО более целесообразно показать просто пример кода, что собственно и делаю.
using (System.Web.Hosting.HostingEnvironment.Impersonate())
{
WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
using (WindowsImpersonationContext context = identity.Impersonate())
{
using (SPSite site = new SPSite(SPContext.Current.Site.Url))
{
site.AllowUnsafeUpdates = true;
using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ServerRelativeUrl)
{
web.AllowUnsafeUpdates = true;
//some code
}
}
}
}