Метод BeforeCall IParameterInspector работает, но не прерывает вызов
Я гуглил и тоже просмотрел этот и этот пост, но у меня все еще есть проблема с тем, что мой звонок не был прерван должным образом. Сценарий таков:
Существует один клиент (сервер), которому разрешен доступ к одной конкретной операции службы, предоставляемой веб-службой. Веб-сервис предоставляет другие методы, которые обычно доступны, только конкретный ограничен одним конкретным IP-адресом. Интерфейс выглядит так:
[ServiceContract( Namespace = "http://some.where/abc/2014/01" )]
public interface IWsConnector : IDisposable
{
[OperationContract( ProtectionLevel = ProtectionLevel.EncryptAndSign )]
[FaultContract( typeof( ServiceFault ) )]
Collection<HostedExchangeObject> GetSomeObjects(
string anIdentifier, int aNumber );
// This is the service operation that shall be protected
[OperationContract( ProtectionLevel = ProtectionLevel.EncryptAndSign )]
[FaultContract( typeof( ServiceFault ) )]
[IpFilter]
Collection<HostedExchangeObject> GetSomeObjectsForInternalUse(
string anIdentifier );
[OperationContract( ProtectionLevel = ProtectionLevel.EncryptAndSign )]
[FaultContract( typeof( ServiceFault ) )]
Collection<HostedExchangeObject> GetSomeObjectsByFlag(
string anIdentifier,
int aNumber,
SomeObjectType someExchangeObjectType );
}
Атрибут IpFilter, используемый для операции службы в интерфейсе, выглядит следующим образом (соответствующие части кода):
[AttributeUsage( AttributeTargets.Method )]
public sealed class IpFilterAttribute : Attribute, IOperationBehavior, IParameterInspector
{
...
public object BeforeCall( string operationName, object[] inputs )
{
RemoteEndpointMessageProperty clientEndpoint =
OperationContext.Current.IncomingMessageProperties[
RemoteEndpointMessageProperty.Name ] as RemoteEndpointMessageProperty;
if ( clientEndpoint != null )
{
IpAddressRange ipAddressRange =
new IpAddressRange(
IPAddress.Parse( RangeFrom ), IPAddress.Parse( RangeTo ) );
if ( !ipAddressRange.IsInRange( IPAddress.Parse( clientEndpoint.Address ) ) )
{
ConditionalLogger conditionalLogger =
new ConditionalLogger( "SomeInformation" );
conditionalLogger.LogAndThrowFaultException(
Severity.Error,
ServiceOperationNotPermittedForRequestingClient,
operationName,
clientEndpoint.Address
);
}
}
return null;
}
...
}
RangeFrom
а также RangeTo
устанавливаются в конструкторе по умолчанию, используя значения из конфигурации (настройки). Причина этого заключается в том, что мы не можем использовать параметры для конструктора, поскольку нам необходимо развернуть их в разных средах, каждая из которых нуждается в разных диапазонах IP-адресов.
Когда я пытаюсь получить доступ к операции службы от клиента в пределах разрешенного диапазона IP-адресов, все работает нормально.
Когда я пытаюсь получить доступ к операции службы от клиента за пределами допустимого диапазона IP-адресов, все работает нормально со стороны клиента (т.е. доступ к операции не разрешен, никакие данные не передаются, кроме FaultException).
Проблема, однако, в том, что на стороне сервера (возможно, длительное выполнение) операция все еще выполняется и не прерывается. не BeforeCall
правильный способ проверить и прервать вызов? После упомянутых выше постов, добавление исключения также должно быть правильным способом прервать вызов, поэтому я не знаю, что еще может быть не так? Как можно избежать того, чтобы код, связанный с этой сервисной операцией, выполнялся на стороне сервера?
1 ответ
Есть ли IpFilterAttribute
будет выполняться во время вызова клиента GetSomeObjectsForInternalUse
метод? бросить исключение внутри BeforeCall
метод Вместо создания исключения внутри ConditionalLogger
и посмотрим, как это работает. и вот хорошая статья о разрешении / запрете доступа по IP-адресу в WCF.
Изменить: попробуйте этот код
public class IpFilterAttribute : Attribute, IOperationBehavior, IParameterInspector
{
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
dispatchOperation.ParameterInspectors.Add(this);
}
public void AddBindingParameters(OperationDescription operationDescription,
BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
public void Validate(OperationDescription operationDescription)
{
}
public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
{
}
public object BeforeCall(string operationName, object[] inputs)
{
var clientEndpoint =
OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as
RemoteEndpointMessageProperty;
throw new SecurityException(string.Format("Calling method '{0}' is not allowed from address '{1}'.",
operationName, clientEndpoint.Address));
return null;
}
}