![](/img/trans.png)
[英]Using IParameterInspector.BeforeCall(string operationName, object[] inputs) to abort a call
[英]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;
}
...
}
使用配置(設置)中的值在默認構造函數中設置RangeFrom
和RangeTo
。 原因是我們無法將參數用於構造函數,因為我們需要部署到不同的環境,每個環境都需要不同的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.