Метод 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;
        }
    }
Другие вопросы по тегам