1

我想对我的服务方法实施调用限制。当达到每个客户端的最大调用量时,这些限制应该返回一个 FaultException。

我发现的第一个解决方案是对服务中的逻辑进行编码:

 public class MyService: IService
 {

    public IList<Entity> FindAll()
    {
        if(VerifyQuota(Context, "FindAll", this.GetType().Name))
        {
           //retrieves entities
            return entities;
        }
        else
        {
           //throws a FaultException
        }
        return null;
    }

    private bool VerifyQuota(ContextEntity context,string Method,String Service)
    {
      // counts the occurences of calls made by the user
      // returns true if user can access method , false otherwise
    }
 }

它有效,但是:

  • 比较丑
  • 它污染了我的方法的逻辑
  • 代码冗余太高,可维护性真的很差。

我正在寻找更优雅的解决方案并考虑使用 IOperationBehavior,但我不知道在哪里可以找到用户身份。

OperationContext.Current 未设置,Thread.CurrentPrincipal 也未设置。

所以这是我的问题: - 行为是实现这种功能的最佳方式吗?- 如果是,我在哪里可以找到用户的身份(或登录) - 如果不是,我可以在哪里放置此代码以使其适合 WCF 架构?

4

1 回答 1

0

我一直在玩 Behaviors,发现我可以在 IparameterInspector 中访问 operationContext.Current。

IparameterInspector 实现:

class QuotaInspector : IParameterInspector
{
    #region IParameterInspector Members

    public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState)
    {

    }

    public object BeforeCall(string operationName, object[] inputs)
    {
        if(ServiceSecurityContext.Current != null)
        {
            if(ServiceSecurityContext.Current.PrimaryIdentity != null
                && ServiceSecurityContext.Current.PrimaryIdentity.AuthenticationType == "MembershipProviderValidator")
            {
                String Account = String.Empty;
                String serviceComponent = String.Empty;
                if(!String.IsNullOrEmpty(ServiceSecurityContext.Current.PrimaryIdentity.Name))
                    Account = ServiceSecurityContext.Current.PrimaryIdentity.Name;
                if(OperationContext.Current != null &&
                    OperationContext.Current.EndpointDispatcher != null
                    && OperationContext.Current.EndpointDispatcher.DispatchRuntime != null
                    && OperationContext.Current.EndpointDispatcher.DispatchRuntime.Type != null &&
                    !String.IsNullOrEmpty(OperationContext.Current.EndpointDispatcher.DispatchRuntime.Type.Name))
                    serviceComponent = ServiceSecurityContext.Current.PrimaryIdentity.Name;
                if(!String.IsNullOrEmpty(Account) && !String.IsNullOrEmpty(serviceComponent) && !string.IsNullOrEmpty(operationName))
                {
                    //Apply Quota verification here
                                            //throw FaultException if quota is reached
                }
            }

        }
        return null;
    }

    #endregion
}

IOperationBehavior 实现:

class QuotaOperationBehavior : Attribute,IOperationBehavior
{
    #region IOperationBehavior Members

    public void AddBindingParameters(OperationDescription operationDescription, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.ClientOperation clientOperation)
    {

    }

    public void ApplyDispatchBehavior(OperationDescription operationDescription, System.ServiceModel.Dispatcher.DispatchOperation dispatchOperation)
    {
        dispatchOperation.ParameterInspectors.Add(new QuotaInspector());
    }

    public void Validate(OperationDescription operationDescription)
    {
    }

    #endregion

}

要将配额应用于方法,您只需声明一个属性:

public class MyService: IService
 {

    [QuotaOperationBehavior]
    public IList<Entity> FindAll()
    {
       //retrieves entities
        return entities;
    }
 }
于 2013-04-26T09:02:37.567 回答