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

ОГЛАВЛЕНИЕ

Реализация структурированных требований размещения

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

Рис. 11 Реализация метода DemandHostPermissions

public static class CodeAccessSecurityHelper {
  internal static void DemandHostPermissions(this ServiceHost host) {
   foreach(ServiceEndpoint endpoint in host.Description.Endpoints) {
    DemandHostConnectionPermissions(endpoint);
    DemandHostSecurityPermissions(endpoint);
    using(TransactionScope scope = new TransactionScope()) {
     DemandTransactionPermissions(endpoint);
    }
   }
   DemandHostStorePermissions(host);
   DemandPerformanceCounterPermissions();
   DemandTracingPermissions();
   DemanAspNetProvidersPermissions(host);
  }
  internal static void DemandHostConnectionPermissions(
   ServiceEndpoint endpoint) {

   PermissionSet connectionSet =
    new PermissionSet(PermissionState.None);
   if(endpoint.Binding is NetTcpBinding) {
    connectionSet.AddPermission(new SocketPermission(
     NetworkAccess.Accept, TransportType.Tcp,
     endpoint.Address.Uri.Host,endpoint.Address.Uri.Port));
   }

   /* Checking the other bindings */

   connectionSet.Demand();
  }

  static void DemanAspNetProvidersPermissions(ServiceHost host) {
   bool demand = false;

   foreach(IServiceBehavior behavior in host.Description.Behaviors) {
    if(behavior is ServiceCredentials) {
     ServiceCredentials credentialsBehavior =
      behavior as ServiceCredentials;

     if(credentialsBehavior.UserNameAuthentication.
      UserNamePasswordValidationMode ==
      UserNamePasswordValidationMode.MembershipProvider) {

      demand = true;
      break;
     }
    }
    if(behavior is ServiceAuthorizationBehavior) {
     ServiceAuthorizationBehavior serviceAuthorization =
      behavior as ServiceAuthorizationBehavior;
     if(serviceAuthorization.PrincipalPermissionMode ==
      PrincipalPermissionMode.UseAspNetRoles &&
      Roles.Enabled) {

      demand = true;
      break;
     }
    }
   }
   if(demand) {
    IPermission permission =
     new AspNetHostingPermission(
     AspNetHostingPermissionLevel.Minimal);
    permission.Demand();
   }
  }
  //Rest of the implementation
}

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

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

Класс AppDomainHost также требует некоторой переработки для поддержки структурированных требований в частично доверенной среде, как показано далее.

[SecurityPermission(
  SecurityAction.Assert,ControlAppDomain = true)]
[ReflectionPermission(
  SecurityAction.Assert,Unrestricted = true)]
public class AppDomainHost : IDisposable {
  protected AppDomainHost(Type serviceType,
   AppDomain appDomain,
   PermissionSet permissions,
   params Uri[] baseAddresses) {
   //Cannot grant service permissions
   // the host does not have
   permissions.Demand();

   //Rest of constructor
   }
}

Поскольку AppDomainHost создает новую область приложения, он утверждает полномочие на управление областью приложений. Поскольку он использует отражение для внедрения размещения в другую область приложений, он подтверждает неограниченные полномочия на отражение. Важнее то, что, прежде чем создавать размещение службы в новой области приложений, класс AppDomainHost запрашивает полномочия для службы у кода, который ее вызывает. Этим гарантируется, что частично доверенный код сможет запускать и размещать только службу, которой позволено столько же, сколько вызывающему коду, но не больше.