2

現在、コンシューマーがユーザー名とパスワードを使用して認証できるようにする WCF SOAP API があります (内部的にUserNamePasswordValidatorを使用します)。参考までに、ユーザー名とパスワードは次のように SOAP 本文で渡されます。

<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" mustUnderstand="1">
<Timestamp Id="_0">
    <Created>
        2013-04-05T16:35:07.341Z</Created>
        <Expires>2013-04-05T16:40:07.341Z</Expires>
    </Timestamp>
    <o:UsernameToken Id="uuid-ac5ffd20-8137-4524-8ea9-3f4f55c0274c-12">
        <o:Username>someusername</o:Username>
        <o:Password o:Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">somepassword
    </o:Password>
</o:UsernameToken>
</o:Security>

コンシューマーがHTTP Authorization ヘッダーでクレデンシャルを Basic 認証またはOAuth ベアラー トークンとして指定できるように、追加でサポートしたいと考えています。

非 SOAP API の認証を実際に行う方法はすでにいくつかありますが、このために作成したクラスを使用するように WCF に指示する方法についてはよく知りません。どうすればこれを達成できますか? これに答えようとする唯一の他の質問はこちらですが、受け入れられた回答はHTTPヘッダーではなくSOAPヘッダーを使用しており、質問者は本質的にあきらめました。

明らかに、どのソリューションも下位互換性が必要です。SOAP セキュリティ ヘッダーで資格情報を指定するコンシューマを引き続きサポートする必要があります。

4

3 に答える 3

2

ServiceAuthorizationManagerHTTP Authorization ヘッダーの承認を処理するために、WCF サービスの実装を検討する必要があります。

から継承するクラスを作成し、System.ServiceModel.ServiceAuthorizationManager1 つ以上のCheckAccess関数をオーバーライドして、着信 Web 要求を調べ、それを許可するか拒否するかを決定します。ラフスケッチ:

public class MyServiceAuthorizationManager: System.ServiceModel.ServiceAuthorizationManager
    {
        public override bool CheckAccess(OperationContext operationContext, ref Message message)
        {
            var reqProp = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
            var authHeader = reqProp.Headers[HttpRequestHeader.Authorization];

            var authorized = // decide if this message is authorized...

            if (!authorized)
            {
                var webContext = new WebOperationContext(operationContext);
                webContext.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
                webContext.OutgoingResponse.Headers.Add(HttpResponseHeader.WwwAuthenticate, String.Format("Bearer realm=\"{0}\"", baseUri.AbsoluteUri));
            }

            return authorized;
        }
}

これを、サービス ホストを作成する WCF サービスに接続します。

    restAPIServiceHost = new DataServiceHost(typeof(API.RestAPIService), restUris);

    var saz = restAPIServiceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
    if (saz == null)
    {
        saz = new ServiceAuthorizationBehavior();
        restAPIServiceHost.Description.Behaviors.Add(saz);
    }

    saz.ServiceAuthorizationManager = new MyServiceAuthorizationManager();

    restAPIServiceHost.Open();

これにより、サービス メソッド自体を変更する必要なく、WCF サービスによって公開されるすべてのメソッドに承認チェックが挿入されます。

MyServiceAuthorizationManager の実装は、web.config マジックを使用して WCF サービスにインストールすることもできますが、直接のコードの方が理解しやすく、デバッグしやすいと思います。

複数の認証チェック システムを同じサービスに適用することは、互いに衝突したり、セキュリティ カバレッジにギャップを残したりすることなく行うのは難しいことに注意してください。SOAP ユーザー資格情報のケースを処理する権限がある場合UserNamePasswordValidator、HTTP Authorization ヘッダーのみを含むメッセージは拒否されます。同様に、ServiceAuthorizationManagerHTTP Authorization ヘッダーのみをチェックする は、SOAP ユーザー資格情報を含む Web 要求に失敗します。おそらく、同じ認証チェックで両方の種類の認証資格表現をチェックする方法を理解する必要があります。たとえば、上記の CheckAccess 関数にコードを追加して、HTTP Authorization ヘッダーがメッセージに存在しない場合に SOAP ユーザー資格情報を検索、抽出、およびテストできます。

複数の認証表現を受け入れる必要がある場合は、優先順位も決定する必要があります。HTTP Authorization ヘッダーが存在する場合、SOAP メッセージに含まれるすべてのものよりも優先されるはずです。HTTP Authorization ヘッダーが存在するが無効な場合、完全停止 - リクエストを無許可として拒否します。SOAP に何が含まれているかは問題ではありません。無効な HTTP Authorization ヘッダーは常に悪いニュースです。HTTP Authorization ヘッダーがまったくない場合は、SOAP ユーザーの資格情報を取得して有効性をテストできる SOAP セキュリティ要素があるかどうかを調べることができます。

于 2013-04-14T05:47:46.750 に答える
0

基本認証の場合、セキュリティ モードをトランスポートに設定することで、WCF が機能するようになりました。

たとえば、web.config では次のようになります。

<system.serviceModel>
  <services>
    <service behaviorConfiguration="DefaultServiceBehavior" name="MyService">
      <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="BasicAuthenticationBinding" name="MyEndpoint" contract="MyContract" />
    </service>
  </services>
  <bindings>
    <basicHttpBinding>
      <binding name="BasicAuthenticationBinding">
        <security mode="Transport">
          <transport clientCredentialType="Basic" />
        </security>
      </binding>
    </basicHttpBinding>
   </bindings>
</system.serviceModel>
于 2016-10-28T11:24:37.933 に答える