web-dev-qa-db-de.com

Wie kann ich einen Benutzernamen/ein Passwort in der Kopfzeile an eine SOAP WCF-Service

Ich versuche, einen Webdienst eines Drittanbieters in Anspruch zu nehmen https://staging.identitymanagement.lexisnexis.com/identity-proofing/services/identityProofingServiceWS/v2?wsdl

Ich habe es bereits als Dienstreferenz hinzugefügt, aber ich bin nicht sicher, wie die Anmeldeinformationen für den Header übergeben werden.

Wie kann ich die Header-Anfrage an dieses Format anpassen lassen?

<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>
20
vts

Es gibt wahrscheinlich einen intelligenteren Weg, aber Sie können die Kopfzeilen wie folgt manuell hinzufügen:

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());
}

Hier ist SecurityHeader eine benutzerdefinierte implementierte Klasse, für die einige andere Klassen erforderlich sind, da ich Attribute zur Konfiguration der XML-Serialisierung verwendet habe:

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

Ich habe das Nonce-Bit nicht zu der UsernameToken-XML hinzugefügt, aber es ist der Password-Datei sehr ähnlich. Das Created-Element muss auch noch hinzugefügt werden, es ist jedoch ein einfacher [XmlElement].

33
Thorarin

Die Antworten oben sind so falsch! Fügen Sie keine benutzerdefinierten Header hinzu. Gemessen an Ihrer Beispiel-XML ist dies ein standardmäßiger WS-Security-Header. WCF unterstützt dies definitiv aus der Box. Wenn Sie eine Servicereferenz hinzufügen, sollten Sie die basicHttpBinding-Bindung in der Konfigurationsdatei erstellen. Sie müssen es ändern, um das Sicherheitselement mit dem Modus TransportWithMessageCredential und das Nachrichtenelement mit clientCredentialType = UserName aufzunehmen:

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

Die obige Konfiguration teilt WCF mit, dass Benutzer-ID/Kennwort im Header SOAP über HTTPS erwartet wird. Sie können dann in Ihrem Code eine ID/ein Kennwort festlegen, bevor Sie einen Anruf tätigen:

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

Wenn dieser spezielle Dienstanbieter nicht vom Standard abweicht, sollte er funktionieren.

57
Sergey

Das Hinzufügen eines benutzerdefinierten hartcodierten Headers kann funktionieren (es kann auch gelegentlich abgelehnt werden), aber es ist absolut der falsche Weg. Der Zweck der WSSE ist Sicherheit. Microsoft hat aus genau diesem Grund die Microsoft Web Services Enhancements 2.0 und anschließend die WSE 3.0 veröffentlicht. Sie müssen dieses Paket installieren ( http://www.Microsoft.com/en-us/download/details.aspx?id=14089 ). 

Die Dokumentation ist nicht leicht zu verstehen, insbesondere für diejenigen, die nicht mit SOAP und der WS-Adressierung gearbeitet haben. Zuallererst ist "BasicHttpBinding" Soap 1.1 und es wird Ihnen nicht der gleiche Nachrichtenkopf wie WSHttpBinding angezeigt. Installieren Sie das Paket und sehen Sie sich die Beispiele an. Sie müssen auf die DLL von WSE 3.0 verweisen, und Sie müssen auch Ihre Nachricht richtig einrichten. Es gibt eine große Anzahl oder Variationen im WS Addressing-Header. Sie suchen nach der UsernameToken-Konfiguration. 

Dies ist eine längere Erklärung, und ich sollte für jeden etwas aufschreiben, da ich nirgendwo die richtige Antwort finde. Sie müssen mindestens mit dem WSE 3.0-Paket beginnen.

2
Robin Briggs

Ich habe eine bessere Methode von hier: WCF: Erstellen von benutzerdefinierten Headern, Hinzufügen und Verwenden dieser Header

Client identifiziert sich selbst
Das Ziel hier ist es, dass der Kunde Informationen liefert welche der Server verwenden kann, um festzustellen, wer die Nachricht sendet. Das Folgender C # -Code fügt einen Header mit dem Namen ClientId hinzu:

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

Dieser Code fügt einen Endpunktheader namens ClientId .__ hinzu. mit einem Wert von OmegaClient, der in den Soap-Header eingefügt werden soll ohne Namensraum.

Benutzerdefinierter Header in der Konfigurationsdatei des Clients
Es gibt einen alternativen Weg von einen benutzerdefinierten Header machen Dies kann in der XML-Konfigurationsdatei von .__ erreicht werden. Der Client, an den alle Nachrichten gesendet wurden, indem der benutzerdefinierte Header als .__ angegeben wurde. Teil des Endpunkts wie folgt:

<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>
0
rebornx

Ich habe customBinding zur web.config hinzugefügt.

<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>

Nachdem ich customBinding hinzugefügt habe, kann ich den Benutzernamen und das Passwort wie folgt an den Kundenservice übergeben:

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

Auf diese Weise können Sie den Benutzernamen und das Kennwort in der Kopfzeile an einen SOAP WCF-Dienst übergeben.

0
Asuman Senol

Offensichtlich ist es schon einige Jahre her, dass dieser Beitrag gelebt hat - aber ich habe es gefunden, als ich nach einem ähnlichen Thema suchte. In unserem Fall mussten wir den Benutzernamen/das Passwort zum Security-Header hinzufügen. Dies unterscheidet sich vom Hinzufügen von Header-Informationen außerhalb der Security-Header. 

Der richtige Weg (für benutzerdefinierte Bindings/authenticationMode = "CertificateOverTransport") (wie in .NET Framework Version 4.6.1) ist das Hinzufügen der Client-Anmeldeinformationen wie üblich:

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

und fügen Sie dann ein "Token" im Sicherheitsbindungselement hinzu - da die Anmeldeinformationen Benutzername/pwd nicht standardmäßig enthalten sind, wenn der Authentifizierungsmodus auf "Zertifikat" gesetzt ist.

Sie können dieses Token wie folgt setzen:

    //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());

Das sollte es tun. Ohne den obigen Code (um das Benutzernamen-Token explizit hinzuzufügen), kann das Festlegen der Benutzernamen-Informationen in den Client-Anmeldeinformationen nicht dazu führen, dass diese Anmeldeinformationen an den Dienst übergeben werden.

0
Phantom2018

Angenommen, Sie rufen einen Webdienst mit HttpWebRequest und HttpWebResponse an, da der .Net-Client die Struktur der WSLD unterstützt, die Sie verwenden möchten.

In diesem Fall können Sie die Sicherheitsanmeldeinformationen wie folgt hinzufügen:

<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>

Sie können SOAPUI verwenden, um die wsse-Sicherheit mithilfe des http-Protokolls abzurufen.

Seien Sie vorsichtig, da dies kein sicheres Szenario ist.

0
Matvi

Angenommen, Sie haben eine Service-Referenz des Namens localhost in Ihrem web.config, so dass Sie wie folgt vorgehen können

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);
0
शेखर