Разграничение доступа из кода в WCF - Размещение области приложений

ОГЛАВЛЕНИЕ

Размещение области приложений

С использующим атрибуты подходом к частично доверенным службам связано несколько проблем. Во-первых, при каждом изменении в работе службы (или вообще любого используемого ею подчиненного класса) потребуется изменять стек атрибутов или заменять файл. Это связывает службу с этими классами и увеличивает расходы на сопровождение.

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

Третье, и наиболее важное, это малая вероятность того, что для большинства служб кто-либо действительно будет заниматься проблемой анализа полномочий безопасности, требуемых для их работы, и тщательно сокращать их исходные полномочия для того, чтобы они работали с минимально возможным числом прав и полномочий. Во всяком случае, именно размещение должно было бы заботиться о том, что касается загружаемой им службы, но, тем не менее, по умолчанию размещение не в состоянии на это повлиять. Класс ServiceHost платформы WCF размещает все службы с полным доверием.

Для размещения, а также для собственной защиты службы было бы предпочтительнее разрешить размещению предоставлять любые полномочия, которые оно считает подходящими для службы. С этой целью я написал класс AppDomainHost, определенный на рис. 4.

Рис. 4 AppDomainHost

public class AppDomainHost : IDisposable {
  //Create new app domain in full trust
  public AppDomainHost(Type serviceType,params Uri[] baseAddresses);
  public AppDomainHost(Type serviceType,string appDomainName,
   params Uri[] baseAddresses);

  //Create new app domain with specified permission set
  public AppDomainHost(Type serviceType,PermissionSet permissions,
   params Uri[] baseAddresses);
  public AppDomainHost(Type serviceType,PermissionSet permissions,
   string appDomainName,params Uri[] baseAddresses);

  //Additional constructors that take standard permission set,
  //permission set filename, and an existing app domain  

  public void Open();
  public void Close();
  public void Abort();

  //More members
}

Класс AppDomainHost можно использовать точно так же, как классc ServiceHost, предоставляемый платформой WCF:

AppDomainHost host = 
  new AppDomainHost(typeof(MyService));
host.Open();

Отличие состоит в том, что класс AppDomainHost будет размещать службу предоставляемого типа в новой области приложения, а не в области вызывающей ее стороны. По умолчанию имя новой области приложений будет состоять из «AppDomain Host for» с добавлением суффикса в виде типа службы и нового идентификатора GUID. Предусмотрена также возможность указывать имя новой области приложений.

AppDomainHost host = 
  new AppDomainHost(typeof(MyService),"My App Domain");
host.Open();

По умолчанию новая область приложений создается с полным доверием. Однако помещение службы в отдельную область приложений является ключом к управлению частично доверенными службами.
AppDomainHost позволяет предоставлять полномочия новой области приложений. Например, на рис. 5 показана служба и размещение, предоставляющее службе достаточно полномочий, необходимых для ее работы.

Рис. 5 Частично доверенная служба

class MyService : IMyContract {
  public void MyMethod() {
   Form form = new TestForm();
   form.ShowDialog();
  }
}

//Hosting code:
PermissionSet permissions =
  new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission(
  SecurityPermissionFlag.Execution));
permissions.AddPermission(new UIPermission(
  UIPermissionWindow.SafeTopLevelWindows));

AppDomainHost host =
  new AppDomainHost(typeof(MyService),permissions);

host.Open();

Можно также использовать файл с набором полномочий, и, в отличие от того, что показано на рис. 3, этот файл необходим только на этапе выполнения, и его можно изменить после развертывания. Важно отметить, что имеется также возможность указывать один из стандартных именованных наборов полномочий. Виртуальная «песочница», предписанная частично доверенным службам, оказывает влияние на все подчиненные классы, которые могут использоваться наряду с возможностью делать вызов извне «песочницы» посредством любой технологии, от .NET Framework 1.0 до WCF.

Единственный размещающий процесс может иметь много экземпляров класса AppDomainHost, каждый из которых размещает службы того же или другого типа, имеющие любые произвольные полномочия, как показано на рис. 6 (используется такое же определение службы, как на рис. 5).

Рис. 6 Служба того же типа с другими полномочиями

//Default is service with full trust
AppDomainHost host0 =
  new AppDomainHost(typeof(MyService),
  "Full Trust App Domain",
  new Uri("net.tcp://localhost:6000"));

host0.Open();

//With just enough permissions to do work
PermissionSet permissions1 =
  new PermissionSet(PermissionState.None);
permissions1.AddPermission(new SecurityPermission(
  SecurityPermissionFlag.Execution));
permissions1.AddPermission(new UIPermission(
  UIPermissionWindow.SafeTopLevelWindows));

AppDomainHost host1 =
  new AppDomainHost(typeof(MyService),permissions1,
  "Partial Trust App Domain",
  new Uri("net.tcp://localhost:6001"));

host1.Open();

//With not enough permissions to do work
PermissionSet permissions2 =
  new PermissionSet(PermissionState.None);
permissions2.AddPermission(new SecurityPermission(
  SecurityPermissionFlag.Execution));

AppDomainHost host2 =
  new AppDomainHost(typeof(MyService),permissions2,
  "Not enough permissions",new Uri("net.tcp://localhost:6002"));

host2.Open();

//Using one of the named permission sets
AppDomainHost host3 =
  new AppDomainHost(typeof(MyService),
  StandardPermissionSet.Internet,
  "Named permission set",
  new Uri("net.tcp://localhost:6003"));

host3.Open();