Как передать имя пользователя/пароль в заголовке SOAP WCF Service - программирование
Подтвердить что ты не робот

Как передать имя пользователя/пароль в заголовке SOAP WCF Service

Я пытаюсь использовать сторонний веб-сервис https://staging.identitymanagement.lexisnexis.com/identity-proofing/services/identityProofingServiceWS/v2?wsdl

Я уже добавил его как ссылку на службу, но я не уверен, как передать учетные данные для заголовка.

Как я могу сделать запрос заголовка соответствующим этому формату?

<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 wsu:Id="UsernameToken-49" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
            <wsse:Username>12345/userID</wsse:Username>
            <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-username-token-profile-1.0#PasswordText">password123</wsse:Password>
            <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">d+VxCZX1cH/ieMkKEr/ofA==</wsse:Nonce>
            <wsu:Created>2012-08-04T20:25:04.038Z</wsu:Created>
        </wsse:UsernameToken>
    </wsse:Security>
</soapenv:Header>
4b9b3361

Ответ 1

Вероятно, есть более умный способ, но вы можете добавить заголовки вручную следующим образом:

var client = new IdentityProofingService.IdentityProofingWSClient();

using (new OperationContextScope(client.InnerChannel))
{
    OperationContext.Current.OutgoingMessageHeaders.Add(
        new SecurityHeader("UsernameToken-49", "12345/userID", "password123"));
    client.invokeIdentityService(new IdentityProofingRequest());
}

Здесь SecurityHeader - это пользовательский реализованный класс, для которого требуется несколько других классов, поскольку я решил использовать атрибуты для настройки сериализации XML:

public class SecurityHeader : MessageHeader
{
    private readonly UsernameToken _usernameToken;

    public SecurityHeader(string id, string username, string password)
    {
        _usernameToken = new UsernameToken(id, username, password);
    }

    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"; }
    }

    protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(UsernameToken));
        serializer.Serialize(writer, _usernameToken);
    }
}


[XmlRoot(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
public class UsernameToken
{
    public UsernameToken()
    {
    }

    public UsernameToken(string id, string username, string password)
    {
        Id = id;
        Username = username;
        Password = new Password() {Value = password};
    }

    [XmlAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")]
    public string Id { get; set; }

    [XmlElement]
    public string Username { get; set; }

    [XmlElement]
    public Password Password { get; set; }
}

public class Password
{
    public Password()
    {
        Type = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
    }

    [XmlAttribute]
    public string Type { get; set; }

    [XmlText]
    public string Value { get; set; }
}

Я не добавил бит Nonce в XML UsernameToken, но он очень похож на Password. Элемент Created также нужно добавить еще, но это простой [XmlElement].

Ответ 2

Ответы выше не так! НЕ добавляйте пользовательские заголовки. Судя по вашему образцу xml, он является стандартным заголовком WS-Security. WCF определенно поддерживает его из коробки. Когда вы добавляете ссылку на службу, вы должны иметь привязку basicHttpBinding, созданную для вас в файле конфигурации. Вам придется изменить его, чтобы включить элемент безопасности в режим TransportWithMessageCredential и элемент сообщения с clientCredentialType = UserName:

<basicHttpBinding>
  <binding name="usernameHttps">
    <security mode="TransportWithMessageCredential">
      <message clientCredentialType="UserName"/>
    </security>
  </binding>
</basicHttpBinding>

В приведенной выше конфигурации говорится, что WCF ожидает идентификатор пользователя/пароль в заголовке SOAP через HTTPS. Затем вы можете установить id/password в своем коде перед выполнением вызова:

var service = new MyServiceClient();
service.ClientCredentials.UserName.UserName = "username";
service.ClientCredentials.UserName.Password = "password";

Если этот конкретный поставщик услуг не отклоняется от стандарта, он должен работать.

Ответ 3

Добавление пользовательского жестко кодированного заголовка может работать (оно также может быть отклонено время от времени), но это совершенно неправильный способ сделать это. Целью WSSE является безопасность. Microsoft выпустила Microsoft Web Services Enhancements 2.0 и впоследствии WSE 3.0 по этой причине. Вам необходимо установить этот пакет (http://www.microsoft.com/en-us/download/details.aspx?id=14089).

Документацию непросто понять, особенно для тех, кто не работал с SOAP и WS-Addressing. Прежде всего, "BasicHttpBinding" - это Soap 1.1, и он не даст вам тот же заголовок сообщения, что и WSHttpBinding. Установите пакет и посмотрите примеры. Вам нужно будет ссылаться на DLL из WSE 3.0, и вам также нужно будет правильно настроить ваше сообщение. В заголовке WS Addressing имеется огромное количество или вариации. Тот, который вы ищете, это конфигурация UsernameToken.

Это более длинное объяснение, и я должен написать что-то для всех, так как я не могу найти правильный ответ нигде. Как минимум вам нужно начать с пакета WSE 3.0.

Ответ 4

Предположим, что у вас есть служебная ссылка имени localhost в вашем web.config, чтобы вы могли идти следующим образом

localhost.Service objWebService = newlocalhost.Service();
localhost.AuthSoapHd objAuthSoapHeader = newlocalhost.AuthSoapHd();
string strUsrName =ConfigurationManager.AppSettings["UserName"];
string strPassword =ConfigurationManager.AppSettings["Password"];

objAuthSoapHeader.strUserName = strUsrName;
objAuthSoapHeader.strPassword = strPassword;

objWebService.AuthSoapHdValue =objAuthSoapHeader;
string str = objWebService.HelloWorld();

Response.Write(str);

Ответ 5

Предположим, что вы вызываете веб-службу с помощью HttpWebRequest и HttpWebResponse, потому что клиент .Net поддерживает структуру WSLD, которую вы пытаетесь использовать.

В этом случае вы можете добавить учетные данные безопасности в заголовках, например:

<soap:Envelpe>
<soap:Header>
    <wsse:Security soap:mustUnderstand='true' xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' xmlns:wsu='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'><wsse:UsernameToken wsu:Id='UsernameToken-3DAJDJSKJDHFJASDKJFKJ234JL2K3H2K3J42'><wsse:Username>YOU_USERNAME/wsse:Username><wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>YOU_PASSWORD</wsse:Password><wsse:Nonce EncodingType='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'>3WSOKcKKm0jdi3943ts1AQ==</wsse:Nonce><wsu:Created>2015-01-12T16:46:58.386Z</wsu:Created></wsse:UsernameToken></wsse:Security>
</soapHeather>
<soap:Body>
</soap:Body>


</soap:Envelope>

Вы можете использовать SOAPUI для получения wsse Security, используя протокол http.

Будьте осторожны, потому что это не безопасный сценарий.

Ответ 6

Я получил лучший метод отсюда: WCF: создание пользовательских заголовков, как добавлять и использовать эти заголовки

Клиент идентифицирует себя
Целью здесь является предоставление клиенту какой-либо информации которые сервер может использовать, чтобы определить, кто отправляет сообщение. следующий код С# добавит заголовок с именем ClientId:

var cl = new ActiveDirectoryClient();

var eab = new EndpointAddressBuilder(cl.Endpoint.Address);

eab.Headers.Add( AddressHeader.CreateAddressHeader("ClientId",       // Header Name
                                                   string.Empty,     // Namespace
                                                    "OmegaClient")); // Header Value
cl.Endpoint.Address = eab.ToEndpointAddress();

// Now do an operation provided by the service.
cl.ProcessInfo("ABC");

Что делает этот код, это добавить заголовок конечной точки с именем ClientId со значением OmegaClient для вставки в заголовок мыла без пространства имен.

Пользовательский заголовок в файле конфигурации клиентов
Существует альтернативный способ делая пользовательский заголовок. Это может быть достигнуто в файле конфигурации Xml клиент, где все сообщения отправляются путем указания настраиваемого заголовка как часть конечной точки:

<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IActiveDirectory" />
            </basicHttpBinding>
        </bindings>
        <client>
          <endpoint address="http://localhost:41863/ActiveDirectoryService.svc"
              binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IActiveDirectory"
              contract="ADService.IActiveDirectory" name="BasicHttpBinding_IActiveDirectory">
            <headers>
              <ClientId>Console_Client</ClientId>
            </headers>
          </endpoint>
        </client>
    </system.serviceModel>
</configuration>

Ответ 7

Очевидно, прошло несколько лет, как этот пост был жив, но на самом деле я нашел его, когда искал похожую проблему. В нашем случае нам пришлось добавить информацию об имени пользователя и пароле в заголовок Security. Это отличается от добавления информации заголовка вне заголовков Security.

Правильный способ сделать это (для пользовательских привязок /authenticationMode = "CertificateOverTransport") (как в .Net Framework версии 4.6.1), это добавить учетные данные клиента как обычно:

    client.ClientCredentials.UserName.UserName = "[username]";
    client.ClientCredentials.UserName.Password = "[password]";

и затем добавьте "токен" в элемент привязки безопасности - поскольку учетные данные имени пользователя /pwd не будут включены по умолчанию, когда для режима аутентификации установлен сертификат.

Вы можете установить этот токен так:

    //Get the current binding 
    System.ServiceModel.Channels.Binding binding = client.Endpoint.Binding;
    //Get the binding elements 
    BindingElementCollection elements = binding.CreateBindingElements();
    //Locate the Security binding element
    SecurityBindingElement security = elements.Find<SecurityBindingElement>();

    //This should not be null - as we are using Certificate authentication anyway
    if (security != null)
    {
    UserNameSecurityTokenParameters uTokenParams = new UserNameSecurityTokenParameters();
    uTokenParams.InclusionMode = SecurityTokenInclusionMode.AlwaysToRecipient;
security.EndpointSupportingTokenParameters.SignedEncrypted.Add(uTokenParams);
    }

   client.Endpoint.Binding = new CustomBinding(elements.ToArray());

Это должно сделать это. Без приведенного выше кода (для явного добавления токена имени пользователя) даже установка информации об имени пользователя в учетных данных клиента может не привести к тому, что эти учетные данные будут переданы в Службу.

Ответ 8

Я добавил customBinding в web.config.

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="CustomSoapBinding">
          <security includeTimestamp="false"
                    authenticationMode="UserNameOverTransport"
                    defaultAlgorithmSuite="Basic256"
                    requireDerivedKeys="false"
                    messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10">
          </security>
          <textMessageEncoding messageVersion="Soap11"></textMessageEncoding>
          <httpsTransport maxReceivedMessageSize="2000000000"/>
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="https://test.com:443/services/testService"
                binding="customBinding"
                bindingConfiguration="CustomSoapBinding"
                contract="testService.test"
                name="test" />
    </client>
  </system.serviceModel>
  <startup>
    <supportedRuntime version="v4.0"
                      sku=".NETFramework,Version=v4.0"/>
  </startup>
</configuration>

После добавления customBinding я могу передать имя пользователя и пароль клиентскому сервису следующим образом:

service.ClientCridentials.UserName.UserName = "testUser";
service.ClientCridentials.UserName.Password = "testPass";

Таким образом, вы можете передать имя пользователя и пароль в заголовке службе SOAP WCF.