Программирование средств безопасности в SharePoint 2007 - Удостоверение, повышение и олицетворение

ОГЛАВЛЕНИЕ

Удостоверение, повышение и олицетворение

Рабочий процесс для веб-приложения WSS Web контролируется через пулы приложений IIS. Удостоверение рабочего процесса для веб-приложения требует внимания пользователя и настраивается через приложение SharePoint Central Administration. Удостоверение рабочего процесса для веб-приложения следует настраивать в терминах учетных записей домена (таких как LITWAREINC\SP_WorkerProcess), а не полагаться на локальные записи (такие как NETWORK SERVICE).

Отметьте, что удостоверение рабочего процесса для веб-приложения должно быть привилегированной учетной записью Windows, с настроенными разрешениями SQL Server на чтение и запись для одной или нескольких баз данных содержимого. Удостоверение рабочего процесса для веб-приложения, на котором работает веб-узел SharePoint Central Administration должно быть еще более привилегированным, поскольку оно требует разрешений на чтение и запись в базу данных настройки фермы.

Когда код, на котором основан веб-компонент или страница приложения, исполняется в ответ на запрос пользователя, исполнение происходит без использования удостоверения рабочего процесса веб-приложения, на котором они размещены. Вместо этого, WSS использует олицетворение для переключения контекста безопасности Windows на другую учетную запись Windows. Если заглянуть в файл web.config file для веб-приложения WSS, можно будет увидеть следующую запись:

<configuration>
  <system.web>
  <identity impersonate="true" />
  </system.web>
</configuration>

Когда запрос исполняется для пользователя, чья подлинность была проверена с помощью учетной записи Windows, запрос олицетворяет удостоверение Windows текущего пользователя. Однако, такой подход невозможен для пользователей FBA, поскольку проверка подлинности FBA не создает маркер безопасности Windows и не имеет удостоверения Windows. Следовательно, запросы для пользователей, использующих проверку подлинности FBA, олицетворяют удостоверение учетной записи Windows, которая была настроена для анонимного доступа. По умолчанию, для такой учетной записи в IIS выделяется учетная запись IUSER_MACHINENAME, но возможно, а обычно и следует, перенастроить все так, чтобы указывалась учетная запись домена.

Теперь самое время рассмотреть безопасность WSS на более высоком уровне. Модель безопасности WSS часто заставляет разработчиков выбирать между удостоверением Windows и удостоверением пользователя WSS . Это может быть не столь очевидно внутри запроса, в котором текущее удостоверение Windows и текущее удостоверение пользователя WSS указывают на одно и то же имя входа Windows. Однако, в ситуациях применения FBA, все несколько усложняется. Например, удостоверение пользователя WSS может указывать на пользователя FBA по имени Эндрю, тогда как базовое удостоверение Windows является основанным на учетной записи IUSER_MACHINENAME. При попытке программного кода получить доступ к объектам WSS, WSS запускает проверки доступа, используя удостоверение WSS пользователя. А по мере попыток кода получить доступ к внешним объектам за пределами WSS, таким как файлы, обслуживаемые операционной системой Windows, ОС запускает проверки доступа, используя удостоверение Windows, под которым код исполняется в настоящий момент.

Встречаются случаи, когда необходимо исполнение кода с большими разрешениями, чем те, которыми владеет текущий пользователь. Например, представьте себе ситуацию, в которой программному коду нужно записать данные в список при обработке запроса от пользователя, у которого имеются только разрешения на чтение. По умолчанию, код работает с теми же разрешениями, что и текущий пользователь. Однако, можно вызвать метод RunWithElevatedPrivileges класса SPSecurity, чтобы повысить контекст безопасности кода. Отметьте, что вызов RunWithElevatedPrivileges повышает удостоверения как пользователя WSS, так и Windows.

Теперь представьте себе ситуацию, в которой пользователь продемонстрировал свою подлинность учетной записи Windows, используя имя входа LITWAREINC\BrianC. Вызов RunWithElevatedPrivileges повысит удостоверение пользователя WSS до уровня учетной записи SHAREPOINT\System. Учетная запись SHAREPOINT\System встроена в среду WSS и всесильна внутри модели проверки подлинности WSS. Вызов RunWithElevatedPrivileges также переключит удостоверение Windows исполняемого кода, так чтобы он работал используя удостоверение рабочего процесса текущего веб-приложения:

// BEFORE ELEVATION
// WSS User identity = LITWAREINC\BrianC
// Windows identity = LITWAREINC\BrianC

SPSecurity.RunWithElevatedPrivileges(delegate() {
  // AFTER ELEVATION
  // WSS User identity = SHAREPOINT\System
  // Windows identity = LITWAREINC\SP_WorkerProcess
});

В некоторых ситуациях, можно воспользоваться вызовом метода RunWithElevatedPrivileges для изменения удостоверения Windows текущего вызова, прежде чем пытаться получить доступ к файлу внутри файловой системы Windows или базы данных SQL Server. Также отметьте, что переключение удостоверения Windows на удостоверение процесса, такое как LITWAREINC\SP_WorkerProcess может устранить необходимость настройки делегирования внутри среды Active Directory. Это может быть очень ценно при наличии специальных веб-компонентов, получающих доступ к данным на удаленной базе данных SQL Server, используя интегрированную проверку подлинности Windows.

Ну и далее можно вспомнить прочие ситуации, в которых может понадобиться вызов метода RunWithElevatedPrivileges, чтобы повысить удостоверение пользователя WSS до уровня SHAREPOINT\System, позволяющее программному коду выполнять операции, не дозволенные текущему пользователю. После того, как код начал работать в качестве SHAREPOINT\System, внутри подсистемы проверки подлинности WSS можно делать практически что угодно.

В вызове RunWithElevatedPrivileges с целью повышения SHAREPOINT\System есть одна каверзная сторона. Для примера, представьте себе вызов RunWithElevatedPrivileges с последующей попыткой получить доступ к объектам на текущем семействе веб-узлов через свойство SPContext.Current. Может показаться, что здесь не стоит ожидать сбоя, но это не так:

SPSecurity.RunWithElevatedPrivileges(delegate() {
  SPSite siteCollection = SPContext.Current.Site;
  // next line fails if current user is Contributor
  string siteCollectionOwner = siteCollection.Owner;
});

Почему в этом примере кода происходит сбой, после повышения удостоверения пользователя WSS до SHAREPOINT\System? Это имеет отношение к моменту создания объекта SPSite. Разрешения, действующие на объекте SPSite и его дочерних объектах SPWeb, не зависят от текущего удостоверения пользователя WSS. Вместо этого, разрешения зависят от удостоверения пользователя WSS в момент создания объекта SPSite. В данном случае, объект SPSite, доступный через PContext.Current был создан ранее в запросе, прежде чем у кода появилась возможность переключить его удостоверение пользователя WSS.

Таким образом, методика, которую следует использовать, требует создания нового объекта SPSite после вызова RunWithElevatedPrivileges и повышения удостоверения пользователя WSS до SHAREPOINT\System:

SPSecurity.RunWithElevatedPrivileges(delegate() {
  using (SPSite elevatedSiteCollection = new SPSite(this.Site.ID)) {
  using (SPWeb elevatedSite =
  elevatedSiteCollection.OpenWeb(this.Web.ID)) {
  // access elevatedSiteCollection and 
  //elevatedSite as SHAREPOINT\System
  }
  }
});

Это делает возможным открытие семейства веб-узлов и веб-узлов внутри него, позволяя коду получать доступ к объектам как SHAREPOINT\System.

Может также оказаться необходимым олицетворение конкретного пользователя WSS. Это является обычным делом при написании кода для обработчика событий, или специального шаблона рабочего потока, в котором код по умолчанию работает как SHAREPOINT\System. Например, олицетворение конкретного пользователя WSS может потребоваться перед созданием нового объекта, так чтобы пользователь WSS был распознан как владелец этого объекта.

Для олицетворения пользователя WSS, сперва необходимо создать объект SPUserToken. Это можно сделать, получив доступ к свойству UserToken объекта SPUser. При наличии объекта SPUserToken, его можно использовать для создания нового объекта SPSite, используя перегруженную версию конструктора классов SPSite. Эта методика показана на рис. 3.

Figure 3 Impersonating a WSS User Identity

SPWeb siteCollection = SPContext.Current.Site;
SPWeb site = SPContext.Current.Web;

// get SPUser object and acquire token
SPUser targetUser = site.SiteUsers[@"LITWAREINC\BrianC"];
SPUserToken token = targetUser.UserToken;

// create new SPSite and SPWeb object to impersonate user
using (SPSite impersonatedSiteCollection = 
  new SPSite(siteCollection.ID, token)) {
  using (SPWeb impersonatedSite = 
  impersonatedSiteCollection.OpenWeb(site.ID)) {
  // WSS identity switched to impersonate BrianC
  // Windows identity does not change
  }
}

Следует отметить несколько важных моментов, относительно олицетворения пользователя WSS. Во-первых, олицетворение пользователя WSS отличается от вызова RunWithElevatedPrivileges тем, что не меняет текущего удостоверения Windows. Если, для примера, запрос работал под удостоверением Windows LITWAREINC\SP_WorkerProcess перед олицетворением пользователя WSS, то запрос продолжит работать под тем же удостоверением Windows. Олицетворение пользователя WSS не меняет текущего удостоверения Windows на удостоверение олицетворяемого пользователя.

Также важно отметить, что код должен работать в привилегированном состоянии, чтобы провести олицетворение другого пользователя. Об этом не стоит беспокоиться при написании кода для обработчика событий, или специального шаблона рабочего потока, поскольку код по умолчанию работает как SHAREPOINT\System. Однако, у кода внутри веб-компонента или в основе страницы приложения может возникнуть необходимость вызвать RunWithElevatedPrivileges прежде чем у него вообще появится возможность олицетворять другого пользователя WSS.