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 を使用することを考えていますが、ユーザー ID をどこで見つけることができるかわかりません。

OperationContext.Current が設定されておらず、Thread.CurrentPrincipal も設定されていません。

ここに私の質問があります: - 動作はこの種の機能を実装するための最良の方法ですか? - その場合、ユーザーの ID (またはログオン) はどこで確認できますか? - そうでない場合、WCF アーキテクチャに適合するようにこのコードをどこに配置できますか?

4

1 に答える 1

0

私はビヘイビアーをいじり続け、IparameterInspector で operatingContext.Curent にアクセスできることを発見しました。

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 に答える