Разграничение доступа из кода в WCF - Реализация структурированных требований на стороне клиента
ОГЛАВЛЕНИЕ
Реализация структурированных требований на стороне клиента
Как уже упоминалось, требования выполняются классом CodeAccessSecurityHelper, частичная реализация которого показана на рис. 7. Все типы полномочий в .NET Framework поддерживают интерфейс IPermission:
Рис. 7 Реализация CodeAccessSecurityHelper (Частичная)
public static class CodeAccessSecurityHelper
{
public static void DemandClientPermissions<T>(this ClientBase<T> proxy,
string operationName) where T : class
{
DemandClientConnectionPermissions(proxy.Endpoint);
DemandTransactionPermissions(proxy.Endpoint,operationName);
DemandTracingPermissions();
DemandClientSecurityPermissions(proxy);
DemandEnvironmentPermissions(proxy);
DemandClientStorePermissions(proxy.Endpoint);
}internal static void DemandClientConnectionPermissions(
ServiceEndpoint endpoint)
{
PermissionSet connectionSet = new PermissionSet(PermissionState.None);if(endpoint.Binding is NetTcpBinding)
{
connectionSet.AddPermission(new SocketPermission(
NetworkAccess.Connect,TransportType.Tcp,
endpoint.Address.Uri.Host,endpoint.Address.Uri.Port));
connectionSet.AddPermission(new DnsPermission(
PermissionState.Unrestricted));
}/* Rest of the bindings */
connectionSet.Demand();
}internal static void DemandTransactionPermissions(
ServiceEndpoint endpoint)
{
DemandTransactionPermissions(endpoint,null);
}internal static void DemandTransactionPermissions(
ServiceEndpoint endpoint, string operationName)
{
bool transactionFlow = false;
bool flowOptionAllowed = false;if(endpoint.Binding is NetTcpBinding)
{
NetTcpBinding tcpBinding = endpoint.Binding as NetTcpBinding;
transactionFlow = tcpBinding.TransactionFlow;
}/* Checking other bindings */
if(transactionFlow)
{
if(Transaction.Current != null)
{
//If operationName is null then at least one operation
//needs to allow flow to trigger demand
foreach(OperationDescription operation in
endpoint.Contract.Operations)
{
string name = operationName ?? operation.Name;
if(name != operation.Name)
{
continue;
}
foreach(IOperationBehavior behavior in operation.Behaviors)
{
if(behavior is TransactionFlowAttribute)
{
TransactionFlowAttribute attribute =
behavior as TransactionFlowAttribute;
if(attribute.Transactions !=
TransactionFlowOption.NotAllowed)
{
flowOptionAllowed = true;
break;
}
}
}
if(flowOptionAllowed)
{
break;
}
}
if(flowOptionAllowed)
{
IPermission distributedTransactionPermission =
new DistributedTransactionPermission(
PermissionState.Unrestricted);
distributedTransactionPermission.Demand();
}
}
}
}
//Rest of the implementation
}public interface IPermission : ...
{
void Demand();
//More members
}
Требование любого полномочия выполняется путем создания экземпляра объекта полномочия и вызова его реализации метода Demand («Потребовать»). При создании набора полномочий можно добавить к нему отдельные полномочия, после чего вызвать Demand на наборе полномочий, чтобы потребовать все полномочия в нем.
Метод расширения DemandClientPermissions, принадлежащий CodeAccessSecurityHelper, выполняет основную часть требований от имени PartialTrustClientBase<T> (использование расширения позволяет использовать его с любым классом прокси). У него имеется набор вспомогательных методов, каждый из которых требует полномочий для своего аспекта. На рис. 7 показан код DemandClientConnectionPermissions, используемый для требования полномочии на подключение в соответствии с привязкой. Он изучает тип привязки, использованный прокси, и добавляет соответствующие полномочия к объекту набора полномочий. После этого он вызывает Demand на наборе полномочий.
Метод DemandTransactionPermissions сперва проверяет, использует ли прокси привязку, способную создать поток транзакции. Если это так, он проверяет наличие у вызывающего клиента транзакции для распространения (значение Transaction.Current отлично от null). Если это так, он проверяет коллекцию операций на предмет контракта конечной точки, ищущего вызванную в настоящий момент операцию. Когда операция найдена, DemandTransactionPermissions извлекает коллекцию поведений операции для данной операции. DemandTransactionPermissions исследует каждое поведение, выполняя поиск TransactionFlowAttribute. Если атрибут настроен на разрешение распространения транзакции, то DemandTransactionPermissions требует полномочия распределенной транзакции. Подобным же образом DemandClientPermissions использует другие вспомогательные методы, чтобы требовать соответствующие полномочия.
Наконец, чтобы включить частично доверенные клиенты и обратные вызовы, я определил класс PartialTrustDuplexClientBase<T,C> и применил его почти так же, как PartialTrustClientBase<T>, за исключением того, что он добавляет поддержку дуплекса для клиентов, получающих обратные вызовы.
На этом заканчивается краткий рассказ о разграничении доступа кода WCF вместе с моим решением по использованию частично доверенных клиентов с соответствующими уровнями полномочий на уровне кода В следующем выпуске рубрики я покажу частично доверенные службы и частично доверенные узлы. В него также будут включены некоторые профессиональные методики программирования для WCF и .NET Framework.