簡體   English   中英

IParameterInspector的BeforeCall方法有效,但不會中止調用

[英]IParameterInspector's BeforeCall method works but does not abort a call

我已經在Google上進行了搜索,也查看了這篇文章這篇文章,但是我的電話仍無法正常中斷。 場景如下:

有一個客戶端(服務器)被允許訪問Web服務提供的一項特定服務操作。 Web服務提供了其他通常可以訪問的方法,只是特定方法僅限於一個特定的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;
    }
    ...
}

使用配置(設置)中的值在默認構造函數中設置RangeFromRangeTo 原因是我們無法將參數用於構造函數,因為我們需要部署到不同的環境,每個環境都需要不同的IP地址范圍。

當我嘗試在允許的IP地址范圍內從客戶端訪問服務操作時,一切正常。

當我嘗試從允許的IP地址范圍之外的客戶端訪問服務操作時,一切都可以從客戶端正常進行 (即,不允許訪問該操作,除了FaultException之外,沒有其他數據可以傳輸)。

但是問題是,在服務器端 ,(可能長時間運行)操作仍在執行中,並且不會中止。 BeforeCall是否不是檢查和中止呼叫的正確方法? 按照上面提到的鏈接文章,拋出異常也應該是終止呼叫的正確方法,所以我不知道還有什么不對嗎? 如何避免與此服務操作關聯的代碼在服務器端執行?

客戶端調用GetSomeObjectsForInternalUse方法時是否將執行IpFilterAttribute 拋出異常中BeforeCall方法,而不是拋出的異常中的ConditionalLogger ,看看它的工作原理。 這是有關WCF中按IP地址允許/拒絕訪問的好文章。

編輯:嘗試此代碼

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;
        }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM