5

私はいくつかの STS サービスにクライアントを構築していますが、1 日以上 WCF メッセージにヘッダーを追加しようとしています。RequestSecurityToken への呼び出しでは、UsernameToken を含める必要があります。

それを達成する方法がわかりません。とりあえず、エンドポイントの動作とメッセージ インスペクターを定義しました (それらを発見するのに十分な時間がかかりました...)。後者の BeforeSendRequest() では、MessageHeader から派生するカスタム クラス 'Security' のオブジェクトを作成します。セキュリティには UsernameToken のインスタンスが含まれます。

public class MessageInspector : IClientMessageInspector {

 public object BeforeSendRequest(ref Message request, IClientChannel channel) {
    Security uns = new Security();
    uns.UsernameToken = new UsernameToken();

    // ...

    var Header = new MessageHeader<Security>(uns);
    var untyped = Header.GetUntypedHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
    request.Headers.Add(untyped);
    return null;
 }
}

public class Security : MessageHeader {
 public UsernameToken UsernameToken = new UsernameToken();

 public override string Name {
    get { return "Security"; }
 }

 public override string Namespace {
    get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
 }
}

public class UsernameToken {
 public String Username = "";
 public Password Password = new Password();
}

連載中のものはこちら

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">urn:RequestSecurityToken</Action>
    <Security xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <UsernameToken xmlns="http://schemas.datacontract.org/2004/07/Tarifrechner.Kfz">
        <Password>
          <Type>http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText</Type>
          <password>******</password>
        </Password>
        <Username>******</Username>
      </UsernameToken>
    </Security>
  </s:Header>
  <s:Body />
</s:Envelope>

特に UsernameToken の名前空間が間違っているようです。データ コントラクトのシリアル化に由来することはわかっていますが、別の名前空間が必要です。

これは、シリアル化されたデータがどのように見えるかです

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="...">
  <soap:Header>
    <Security xmlns:q1="http://www.bipro.net/namespace" xsi:type="q1:UserNameSecurity" 
          xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <UsernameToken>
        <Username>******</Username>
        <Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">******</Password>
      </UsernameToken>
    </Security>
    <wsa:Action>urn:RequestSecurityToken</wsa:Action>
    <wsse:Security>
      <wsu:Timestamp wsu:Id="Timestamp-b9dd599d-5901-451d-8321-6a309091f273">
        <wsu:Created>2012-03-11T16:02:56Z</wsu:Created>
        <wsu:Expires>2012-03-11T16:07:56Z</wsu:Expires>
      </wsu:Timestamp>
    </wsse:Security>
  </soap:Header>
  <soap:Body>
    <RequestSecurityToken xmlns="http://schemas.xmlsoap.org/ws/2005/02/trust">
      <TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</TokenType>
      <RequestType>
        http://schemas.xmlsoap.org/ws/2005/02/trust/Issue
      </RequestType>
    </RequestSecurityToken>
  </soap:Body>
</soap:Envelope>

私のアプローチは正しいですか?また、ヘッダーの詳細の名前空間や、データが属性としてシリアル化されているか要素としてシリアル化されているかなどを操作するにはどうすればよいでしょうか?

アップデート


Ladislav が既に述べたように、UsernameToken のようなクラスを自分で実装する必要はありません。WCF に関する私の知識が非常に限られているという理由だけでそれを行いました。

ここまでで、SecurityMode.TransportWithMessageCredential を使用するように構成され、EstablishSecurityContext を false に設定した WS2007HttpBinding が、探している XML のほとんどを生成することを発見しました。どうやってそれを知っていたのですか?

しかし、1 つ問題が残っています。私の要求には空の body 要素があり、生成したい要求は body 要素内に RequestSecurityToken 要素を備えています。どうすればそれを達成できるか知っていますか?

EstablishSecurityContext = true を使用すると役立ちますが、同時に、私の Soap-Action を目的の「urn:RequestSecurityToken」から機能しない「http://docs.oasis-open.org/ws-sx/ws-trust/200512」に変更します。 /RST/SCT".


私はどんな答えにも感謝します!

どうもありがとう!

ビョルン

4

2 に答える 2

1

別の方法の 1 つは、リクエストのMessageContractタイプを定義することです。これにより、SOAP メッセージのヘッダーと本文に表示される内容を定義し、使用する名前空間を調整できます。たとえば、次のサービス定義について考えてみます。

[ServiceContract]
    public interface IMyService
    {
        [OperationContract]
        MyResponse DoSomething(MyRequest request);
    }

    public class MyService : IMyService
    {
        public MyResponse DoSomething(MyRequest request)
        {
            return new MyResponse()
            {
                Details = "Service did something awesome.",
                Timestamp = DateTime.Now
            };
        }
    }

    [MessageContract(IsWrapped = true, WrapperNamespace = "http://myservice/messages/")]
    public class MyRequest
    {
        [MessageHeader(Namespace = "http://myservice/security")]
        public string TokenThingy
        {
            get;
            set;
        }
    }

    [MessageContract(IsWrapped = true, WrapperNamespace = "http://myservice/messages")]
    public class MyResponse
    {
        [MessageBodyMember]
        public string Details
        {
            get;
            set;
        }

        [MessageBodyMember]
        public DateTime Timestamp
        {
            get;
            set;
        }
    }

リクエストを送信すると、次の SOAP が生成されます。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://tempuri.org/IMyService/DoSomething</Action>
    <h:TokenThingy xmlns:h="http://myservice/security">fda</h:TokenThingy>
  </s:Header>
  <s:Body>
    <MyRequest xmlns="http://myservice/messages/" />
  </s:Body>
</s:Envelope>

サービスからの応答は次のようになります。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body>
    <MyResponse xmlns="http://myservice/messages">
      <Details xmlns="http://tempuri.org/">Service did something awesome.</Details>
      <Timestamp xmlns="http://tempuri.org/">2012-05-04T17:04:36.5980424-04:00</Timestamp>
    </MyResponse>
  </s:Body>
</s:Envelope>
于 2012-05-04T21:12:13.343 に答える
0

メッセージにヘッダーを追加するには、ヘッダー コンテンツをどのように制御する必要があるか、およびヘッダーを挿入する必要がある場所に応じて、いくつかの方法があります。

アプリケーション コードでは、リクエスト プロパティの一部を変更するために、リクエストの周りに OperationContextScope を作成できます。OperationContextScope 内には、OperationContext.Current の有効なインスタンスがあり、これにより、OutgoingMessageHeaders コレクションを介してメッセージ ヘッダーを操作できます。このメソッドを使用すると、ヘッダーの制御がアプリケーション コードに深く組み込まれます。必要に応じて適切なコードをコピーする必要があります。

これらの 2 つのリンク (WCF チームの誰かから) では、大量のコード サンプルを使用して、これについて詳しく説明しています。

于 2012-04-27T14:57:46.743 に答える