it-swarm.com.de

JAX-WS - Hinzufügen SOAP Kopfzeilen

Ich versuche, einen eigenständigen Client zu erstellen, um einige Webdienste zu nutzen. Ich muss meinen Benutzernamen und mein Passwort zum SOAP - Header hinzufügen. Ich habe versucht, die Anmeldeinformationen wie folgt hinzuzufügen:

OTSWebSvcsService service = new OTSWebSvcsService();
OTSWebSvcs port = service.getOTSWebSvcs();

BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");

...

Wenn ich eine Methode im Dienst anrufe, erhalte ich die folgende Ausnahme:

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5048E: One of "SOAP Header" elements required.

Was mache ich falsch? Wie füge ich diese Eigenschaften zum SOAP - Header hinzu? 

Editiert: Ich habe JAX-WS 2.1 in JDK6 verwendet. Ich verwende jetzt JAX-WS 2.2. Ich bekomme jetzt die folgende Ausnahme:

com.ibm.wsspi.wssecurity.SoapSecurityException: WSEC5509E: A security token whose type is [http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken] is required.

Wie kann ich dieses Token erstellen?

29
Jordan Allan

Nicht 100% sicher, da der Frage einige Details fehlen. Wenn Sie jedoch JAX-WS RI verwenden, lesen Sie Hinzufügen von SOAP -Headern beim Senden von Anforderungen :

Die übertragbare Methode hierfür ist, dass Sie eine SOAPHandler erstellen und sich mit SAAJ anlegen. Die RI bietet jedoch eine bessere Möglichkeit, dies zu tun.

Wenn Sie ein Proxy- oder Dispatch-Objekt erstellen, implementieren sie die Schnittstelle BindingProvider. Wenn Sie JAX-WS RI verwenden, können Sie einen Downcast auf WSBindingProvider ausführen, wodurch einige weitere Methoden definiert werden, die nur von JAX-WS RI bereitgestellt werden.

Mit dieser Schnittstelle können Sie eine beliebige Anzahl von Header-Objekten festlegen, die jeweils einen SOAP -Header darstellen. Sie können es auf eigene Faust implementieren, aber höchstwahrscheinlich würden Sie eine der Factory-Methoden verwenden, die in der Klasse Headers definiert sind, um eine zu erstellen.

import com.Sun.xml.ws.developer.WSBindingProvider;

HelloPort port = helloService.getHelloPort();  // or something like that...
WSBindingProvider bp = (WSBindingProvider)port;

bp.setOutboundHeader(
  // simple string value as a header, like <simpleHeader>stringValue</simpleHeader>
  Headers.create(new QName("simpleHeader"),"stringValue"),
  // create a header from JAXB object
  Headers.create(jaxbContext,myJaxbObject)
);

Aktualisieren Sie Ihren Code entsprechend und versuchen Sie es erneut. Wenn Sie JAX-WS RI nicht verwenden, aktualisieren Sie Ihre Frage und geben Sie weitere Kontextinformationen an.

Update: Es scheint, dass der Webdienst, den Sie aufrufen möchten, mit WS-Security/UsernameTokens gesichert ist. Dies unterscheidet sich ein wenig von Ihrer ursprünglichen Frage. Um Ihren Client für das Senden von Benutzernamen und Kennwörtern zu konfigurieren, empfehle ich, den großen Beitrag zu lesen . Implementieren des WS-Security-UsernameToken-Profils für Metro-basierte Webdienste (springen Sie zu Schritt 4). . Die Verwendung von NetBeans für diesen Schritt kann die Arbeit erheblich erleichtern.

27
Pascal Thivent

Entschuldigung für mein schlechtes Englisch. Daten können im SOAP - Header (JaxWS) übertragen werden, indem @WebParam (header = true) wie folgt verwendet wird:

@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/")
@Oneway
public void sendRequest(
    @WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message")
    Data message,
    @WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader")
    Header serviceHeader);

Wenn Sie einen Client mit SOAP -Heatern generieren möchten, müssen Sie -XadditionalHeaders wie folgt verwenden:

wsimport -keep -Xnocompile -XadditionalHeaders -Xdebug http://12.34.56.78:8080/TestHeaders/somewsdl?wsdl -d /home/evgeny/DEVELOPMENT/Java/gen

Wenn Sie keinen @Oneway-Webservice benötigen, können Sie Holder wie folgt verwenden:

@WebMethod(operationName = "SendRequest", action = "http://abcd.ru/")
public void sendRequest(
    @WebParam(name = "Message", targetNamespace = "http://abcd.ru/", partName = "Message")
    Data message,
    @WebParam(name = "ServiceHeader", targetNamespace = "http://abcd.ru/", header = true, partName = "ServiceHeader")
    Holder<Header> serviceHeader);
28
Evgeny

Wenn Sie Maven zum Erstellen Ihres Projekts verwenden, müssen Sie die folgende Abhängigkeit hinzufügen:

    <dependency>
        <groupId>com.Sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>{currentversion}/version>
    </dependency>

Damit erhalten Sie die Klasse com.Sun.xml.ws.developer.WSBindingProvider.

Link: https://mvnrepository.com/artifact/com.Sun.xml.ws/jaxws-rt

7
cristianoms

Verwenden Sie maven und das Plugin jaxws-maven-plugin . Dadurch wird ein Web-Service-Client generiert. Stellen Sie sicher, dass Sie xadditionalHeaders auf true setzen. Dadurch werden Methoden mit Header-Eingaben generiert.

2
Eduardo Dennis

Ich füge diese Antwort hinzu, weil keiner der anderen für mich gearbeitet hat.

Ich musste einen Header Handler zum Proxy hinzufügen:

import Java.util.Set;
import Java.util.TreeSet;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPHeader;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> {

    private final String authenticatedToken;

    public SOAPHeaderHandler(String authenticatedToken) {
        this.authenticatedToken = authenticatedToken;
    }

    public boolean handleMessage(SOAPMessageContext context) {
        Boolean outboundProperty =
                (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (outboundProperty.booleanValue()) {
            try {
                SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
                SOAPFactory factory = SOAPFactory.newInstance();
                String prefix = "urn";
                String uri = "urn:xxxx";
                SOAPElement securityElem =
                        factory.createElement("Element", prefix, uri);
                SOAPElement tokenElem =
                        factory.createElement("Element2", prefix, uri);
                tokenElem.addTextNode(authenticatedToken);
                securityElem.addChildElement(tokenElem);
                SOAPHeader header = envelope.addHeader();
                header.addChildElement(securityElem);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            // inbound
        }
        return true;
    }

    public Set<QName> getHeaders() {
        return new TreeSet();
    }

    public boolean handleFault(SOAPMessageContext context) {
        return false;
    }

    public void close(MessageContext context) {
        //
    }
}

Im Proxy füge ich einfach den Handler hinzu:

BindingProvider bp =(BindingProvider)basicHttpBindingAuthentication;
bp.getBinding().getHandlerChain().add(new SOAPHeaderHandler(authenticatedToken));
bp.getBinding().getHandlerChain().add(new SOAPLoggingHandler());
1
edubriguenti

sie können den Benutzernamen und das Kennwort zum SOAP - Header hinzufügen

BindingProvider prov = (BindingProvider)port;
prov.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                "your end point"));
Map<String, List<String>> headers = new HashMap<String, List<String>>();
prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "myusername");
prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "mypassword");
prov.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);
1
MahmoudPrime

In jaxws-rt-2.2.10-ources.jar!\com\Sun\xml\ws\transport\http\client\HttpTransportPipe.Java:

public Packet process(Packet request) {
        Map<String, List<String>> userHeaders = (Map<String, List<String>>) request.invocationProperties.get(MessageContext.HTTP_REQUEST_HEADERS);
        if (userHeaders != null) {
            reqHeaders.putAll(userHeaders);

Daher wird Map<String, List<String>> Aus requestContext mit dem Schlüssel MessageContext.HTTP_REQUEST_HEADERS In die Header von SOAP. Beispiel für Anwendungsauthentifizierung mit JAX-WS über Header kopiert =

Die Tasten BindingProvider.USERNAME_PROPERTY Und BindingProvider.PASSWORD_PROPERTY Werden in HttpTransportPipe.addBasicAuth() auf besondere Weise verarbeitet, wobei die Standard-Grundberechtigungs-Kopfzeile Authorization hinzugefügt wird.

Siehe auch Nachrichtenkontext in JAX-WS

0
GKislin

Ich habe mit allen Antworten hier zu kämpfen, angefangen mit Pascals Lösung , was schwieriger wird, wenn der Java-Compiler standardmäßig nicht mehr mit rt.jar verbindlich ist (und die Verwendung interner Klassen dies für die Laufzeitimplementierung spezifisch macht). 

Die Antwort von edubriguenti brachte mich näher. Die Art und Weise, wie der Handler mit dem letzten Code-Code verbunden ist, funktionierte für mich jedoch nicht - er wurde nie aufgerufen.

Am Ende verwendete ich eine Variation seiner Handler-Klasse, verdrahtete sie jedoch wie folgt in die javax.xml.ws.Service-Instanz:

Service service = Service.create(url, qname); service.setHandlerResolver( portInfo -> Collections.singletonList(new SOAPHeaderHandler(handlerArgs)) );

0
Peter Becker

Die beste Option (für mich natürlich) ist es, es zu tun. Dies bedeutet, dass Sie alle Teile der Nachricht SOAP programmgesteuert ändern können

Binding binding = prov.getBinding();
   List<Handler> handlerChain = binding.getHandlerChain();
    handlerChain.add( new ModifyMessageHandler() );
    binding.setHandlerChain( handlerChain ); 

Und die ModifyMessageHandler-Quelle könnte sein 

@Override
public boolean handleMessage( SOAPMessageContext context )
{
    SOAPMessage msg = context.getMessage(); 
    try
    {

        SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
        SOAPHeader header = envelope.addHeader();
        SOAPElement ele = header.addChildElement( new QName( "http://uri", "name_of_header" ) );
        ele.addTextNode( "value_of_header" );
        ele = header.addChildElement( new QName( "http://uri", "name_of_header" ) );
        ele.addTextNode( "value_of_header" );
        ele = header.addChildElement( new QName( "http://uri", "name_of_header" ) );
        ele.addTextNode( "value_of_header" );

...

Ich hoffe das hilft dir

0
rumberomelo