1

カスタム バインディングを使用して、UsernameToken で SOAP ヘッダーを渡す認証 Web サービスを使用しようとしています。

ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpsTransportBindingElement httpBindingElement = new HttpsTransportBindingElement();
CustomTextMessageBindingElement textBindingElement = new CustomTextMessageBindingElement();
SecurityBindingElement securityElement = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
securityElement.IncludeTimestamp = false;
bindingElements.Add(securityElement);
bindingElements.Add(textBindingElement);
bindingElements.Add(httpBindingElement);
CustomBinding binding = new CustomBinding(bindingElements);

EndpointAddress address = new EndpointAddress("https://....");

var client = new WebServiceClient(binding, address);
client.ClientCredentials.UserName.UserName = "USERNAME HERE";
client.ClientCredentials.UserName.Password = "PASSWORD HERE";

using (new OperationContextScope(client.InnerChannel))
{
    var req = new WebServiceRequest();
    var resp = client.initiate(req);
}

例外を取得する:

メッセージのセキュリティ検証に失敗しました。

BinarySecretSecurityToken の ' http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd ' 名前空間を持つ 'BinarySecurityToken' 要素からトークンを読み取れません。「oblix:ObSSOCookie」ValueType。この要素が有効であると予想される場合は、指定された名前、名前空間、および値の型を持つトークンを消費するようにセキュリティが構成されていることを確認してください。"}

サーバー スタック トレース:

System.ServiceModel.Security.TransportSecurityProtocol.VerifyIncomingMessage (メッセージ & メッセージ、TimeSpan タイムアウト) で System.ServiceModel.Security.SecurityProtocol.VerifyIncomingMessage (メッセージ & メッセージ、TimeSpan タイムアウト、SecurityProtocolCorrelationState [] correlationStates) で1.SecurityRequestChannel.ProcessReply(Message reply, SecurityProtocolCorrelationState correlationState, TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelFactory1.System.ServiceModel.Dispatcher.RequestChannelBinder.Request(メッセージ メッセージ、TimeSpan タイムアウト) での SecurityRequestChannel.Request(メッセージ メッセージ、TimeSpan タイムアウト) System.ServiceModel.Channels.ServiceChannel.Call(文字列アクション、Boolean oneway、ProxyOperationRuntime 操作、オブジェクト[] ins、Object[] outs、TimeSpan タイムアウト) System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall、ProxyOperationRuntime 操作) で System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage メッセージ)

フィドラーがキャッチした応答は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
    <env:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="oblix:ObSSOCookie" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:oblix="http://schemas.oblix.com/ws/2004/04/authentication"><!--REMOVED--></wsse:BinarySecurityToken>
        </wsse:Security>
    </env:Header>
    <env:Body>
        <MobileAppsLoginSSOProcessResponse  xmlns="http://xmlns.oracle.com/MobileAppsLoginSSO">
            <ReturnStatus>SUCCESS</ReturnStatus>
        </MobileAppsLoginSSOProcessResponse>
    </env:Body>
</env:Envelope>

http://msdn.microsoft.com/en-us/library/ms751486%28v=vs.100%29.aspxに従って CustomTextMessageEncoder を使用しています

編集:

Yaron が示唆しているように、応答から BinarySecurityToken タグを取り除かない限り、コードは上記の Message Security Validation Failed 例外で失敗します。

応答の「oblix:ObSSOCookie」は、認証が成功したときにサービスからクライアントに返される認証 Cookie であり、クライアントはこの Cookie を保存する必要があると思います。

解決策: 最終編集で Yaron が提案したようにSecurityElementBinding、カスタム バインディングから削除し、カスタム メッセージ インスペクター ( IClientMessageInspector) を使用してヘッダーにセキュリティ タグを挿入しました。

AfterReceiveReplyこれにより、SOAP 本文からのみ応答を解釈できるようになり、IClientMessageInspector実装の SOAP 応答ヘッダーを読み取ることができます。

4

1 に答える 1

1

サーバーは応答で x.509 トークンを返しますが、WCF はそれをどう処理すればよいかわかりません (このトークンはユーザー名認証では想定されていません)。2 つのオプションが表示されます。

  1. エンコーダーで、応答からセキュリティ タグを取り除きます

    また

  2. セキュリティをまったく使用せず、エンコーダー (または必要に応じてメッセージ インスペクター) でユーザー/パス ヘッダーを要求にプッシュします。

編集:このトークンは、クライアントがその後の呼び出しで使用する必要があると言います。これを処理する正しい方法がわからないので、動作する簡単な方法を示します (ただし、少し不安定に感じます)。セキュリティをまったく定義しないでください (セキュリティ要素をバインディングから削除します)。次に、カスタム メッセージ インスペクター (またはエンコーダーですが、より困難です) を使用して、正しい形式でユーザー/パスをメッセージにプッシュします (セキュリティ バインディングが使用されている場合にメッセージがどのように送信されるかを確認してください)。これは難しいことではありません。その場合、WCF は応答時にトークンを検証しません。すでに用意されているのと同じメッセージ インスペクターを使用して、応答を検査し、トークンを抽出できます。メイン クラス (プロキシを初期化する) は、インスペクターを初期化したクラスでもあるため、トークンにアクセスして再送信するには、データ メンバーにアクセスできる必要があります。

サーバーがヘッダーではなく本文内でトークンを送信すると、はるかに簡単になります。また、カスタムトークン/動作を実装することにより、パッチのない方法でそれを行う方法があるかもしれませんが、私の考えでは、これにより抽象化が追加され、具体的である方がよいでしょう。

于 2013-08-16T12:45:59.240 に答える