Клиент WCF передает маркер имени пользователя с обязательным значением trueUnderstand - PullRequest
7 голосов
/ 07 ноября 2011

Мне поручено создать службу WCF, которая будет использоваться внешним клиентом.Клиент использует безопасность WSSE, в частности, он передает маркер имени пользователя через заголовок SOAP.

Служба WCF размещается на сервере IIS с включенным SSL.

На данный момент у меня есть полуработающий прототип.Проблема, с которой я сейчас имею дело, заключается в том, что в заголовке SOAP атрибут mustUnderstand установлен в 1, что приводит к сбою процесса.

Мне нужен совет (или, что еще лучше, пример кода улыбается ) о том, как обрабатывать токен имени пользователя таким образом, чтобы он возвращал правильный ответ, когда атрибут mustUnderstand имеет значениеtrue.

Вот пример запроса SOAP, который не выполняется:

    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
       <soapenv:Header>
          <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
             <wsse:UsernameToken>
                <wsse:Username>TestUser</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPWD</wsse:Password>
                <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">NzU3MjFhN2YtYTlmYS00ZWZjLTkxNjktY2ExZjlkZDEwNzE5</wsse:Nonce>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2011-10-26T03:04:39Z</wsu:Created>
             </wsse:UsernameToken>
          </wsse:Security>
       </soapenv:Header>
       <soapenv:Body>
          <tem:Getstuff>
             <tem:Arg1>Arg1</tem:Arg1>
             <tem:Arg2>Arg2</tem:Arg2>
          </tem:Getstuff>
       </soapenv:Body>
    </soapenv:Envelope>

Если soapenv: mustUnderstand = "1" изменено на soapenv: mustUnderstand = "0", тогда процесс работает.


PS: Вот пересмотренный пример запроса, который отправил клиент:

    <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/WService/Getstuff</Action>
        <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="removed" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:Username>TestUser</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">TestPass</wsse:Password>
            <wsse:Nonce>2Udx78sh2y2xRJYJpZZ9+w==</wsse:Nonce>
            <wsu:Created>2011-09-26T19:12:48Z</wsu:Created>
          </wsse:UsernameToken>
        </Security>
      </s:Header>
      <s:Body>
        <Getstuff xmlns="http://tempuri.org/">
         <Arg1>Arg1</Arg1>
         <Arg2>Arg2</Arg2>
        </Getstuff>
      </s:Body>
    </s:Envelope>

Я получил следующий ответ на вышеуказанные запросы:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
       <s:Body>
          <s:Fault>
             <faultcode>s:MustUnderstand</faultcode>
             <faultstring xml:lang="en-US">The header 'Security' from the namespace 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' was not understood by the recipient of this message, causing the message to not be processed.  This error typically indicates that the sender of this message has enabled a communication protocol that the receiver cannot process.  Please ensure that the configuration of the client's binding is consistent with the service's binding.</faultstring>
          </s:Fault>
       </s:Body>
    </s:Envelope>

Вотпереплет:

<bindings>
  <basicHttpBinding>
    <binding name="TransportBind" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
      maxReceivedMessageSize="2147483647">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <security mode="Transport">
        <transport clientCredentialType="None" />
      </security>
    </binding>
    <binding name="basic" maxBufferSize="2147483647" maxBufferPoolSize="2147483647"
      maxReceivedMessageSize="2147483647">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
    </binding>
  </basicHttpBinding>
</bindings>

Ответы [ 3 ]

2 голосов
/ 08 ноября 2011

Ваша привязка basicHttpBinding. Вам нужно использовать wsHttpBinding.

1 голос
/ 15 октября 2012

Я решил эту проблему, не используя сгенерированный заголовок WS-Security (при добавлении ссылки на службу) в конфигурации WCF, а закомментировав это и вместо этого позволив .NET сгенерировать сам заголовок, используя учетные данные клиента и указавРежим безопасности «TransportWithMessageCredential»:

client.ClientCredentials.UserName.UserName = "UserName";
client.ClientCredentials.UserName.Password = "Password";

<basicHttpBinding>
   <binding name="Binding">
      <security mode="TransportWithMessageCredential">
          <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
          <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
   </binding>
</basicHttpBinding>

(Мы используем SSL, поэтому отсюда и этот параметр безопасности).

Закомментированный сгенерированный заголовок:

 <client>
        <endpoint ...>
            <!--<headers>
                <wsse:Security...>
                </wsse:Security>
            </headers>-->
        </endpoint>
 </client>

К сожалению, я не знаю достаточно WCF, чтобы захватить необработанный запрос / ответ мыла, чтобы сравнить разницу и понять, почему ClientCredentials не вызывает ошибку «не было понято», а сгенерированный заголовок -.

Каккроме в соответствии с документацией MSDN , если вы используете только «Транспорт», он не будет знать об использовании WS-Security: «Оставьте это свойство в значении по умолчанию, то есть System.ServiceModel.SecurityMode.Transportне использовать WS-Security. "

0 голосов
/ 08 ноября 2011

+ 1 @JohnSaunders, потому что он, скорее всего, лает здесь на правильное дерево.

Ваш клиент .NET / WCF? В противном случае он может не реализовывать WS-Security или, по крайней мере, не так, как этого хочет WCF.

Если клиент - .NET, это просто несовпадающая привязка на стороне клиента.

Флаг mustUnderstand говорит о том, что заголовок WS-Security должен быть подтвержден и обработан. Клиент, не относящийся к WS-Security, будь то потому, что он не говорит по WS-Security или не настроен на него, будет игнорировать заголовок, все равно попытаться использовать сообщение, и сервер загрузится.

Другой вариант - включить отказ на сервере. Это прекратит посылать заголовки WS-Security. Конечно, тогда вы не получите отказа.

...