Разграничение доступа из кода в 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 запрашивает полномочия для службы у кода, который ее вызывает. Этим гарантируется, что частично доверенный код сможет запускать и размещать только службу, которой позволено столько же, сколько вызывающему коду, но не больше.