2010-06-22 8 views
19

Ho una semplice applicazione Java JAX-WS da riga di comando per testare una richiesta SOAP, ma il server si aspetta che il tipo di password sia PasswordText e sono impantanato su come impostarlo. ..Tipo di password JAX-WS PasswordText

il codice è in questo modo:

@WebServiceRef 
private static final HelloService helloService = new HelloService(url, new QName(
     URL, "HelloService")); 

public static void main(final String... args) { 

    try { 
     final HelloPort helloPort = helloService.getHelloPort(); 
     final BindingProvider hB = ((BindingProvider) helloPort); 
     hB.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, 
            END_POINT_ADDRESS); 
     hB.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, 
            USERNAME); 
     hB.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, 
            PASSWORD); 
     ... 

ho testato la richiesta utilizzando SOAP-UI quindi so che sta funzionando. Sarebbe gradito qualsiasi aiuto sull'impostazione del tipo di password.

Grazie.

risposta

28

Ciò imposterà il nome utente e la password per l'autenticazione HTTP di base. Se lo hai testato in SoapUI, suppongo che il valore "PasswordText" di cui parli sia il "Tipo di password WSS" nel riquadro dei dettagli della richiesta. Questo imposta la sicurezza WSS, non la sicurezza HTTP.

Con JAX-WS in Java6 è necessario collegare un SOAPHandler per iniettare il token WSS-User nell'header SOAP. Ci sono un sacco di bit su questo giro della rete, ma non ho trovato un singolo link per postare, quindi ecco un po 'di codice invece di farti andare ...

Per aggiungere un gestore hai bisogno di qualcosa del tipo:

final Binding binding = ((BindingProvider) servicePort).getBinding(); 
List<Handler> handlerList = binding.getHandlerChain(); 
if (handlerList == null) 
    handlerList = new ArrayList<Handler>(); 

handlerList.add(new SecurityHandler()); 
binding.setHandlerChain(handlerList); // <- important! 

Quindi la classe SecurityHandler farà l'atto. Gli handler sono cose generali e vengono richiamati sia per i messaggi di successo che per i guasti, ma forse più importante vengono chiamati in entrambe le direzioni del messaggio - per la richiesta in uscita e poi di nuovo per la risposta in arrivo. Vuoi solo gestire i messaggi in uscita. Quindi avrete bisogno di qualcosa di simile:

public final class SecurityHandler implements SOAPHandler<SOAPMessageContext> { 

    ... 

    @Override 
    public boolean handleMessage(final SOAPMessageContext msgCtx) { 

     // Indicator telling us which direction this message is going in 
     final Boolean outInd = (Boolean) msgCtx.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 

     // Handler must only add security headers to outbound messages 
     if (outInd.booleanValue()) { 
      try { 
       // Get the SOAP Envelope 
       final SOAPEnvelope envelope = msgCtx.getMessage().getSOAPPart().getEnvelope(); 

       // Header may or may not exist yet 
       SOAPHeader header = envelope.getHeader(); 
       if (header == null) 
        header = envelope.addHeader(); 

       // Add WSS Usertoken Element Tree 
       final SOAPElement security = header.addChildElement("Security", "wsse", 
         "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
       final SOAPElement userToken = security.addChildElement("UsernameToken", "wsse"); 
       userToken.addChildElement("Username", "wsse").addTextNode("MyWSSUsername"); 
       userToken.addChildElement("Password", "wsse").addTextNode("MyWSSPassword"); 

      } catch (final Exception e) { 
       LOG.error(e); 
       return false; 
      } 
     } 
     return true; 
    } 

    ... 
    // Other required methods on interface need no guts 
} 

che ho fatto un paio di ipotesi qui, ma si spera che ti farti andare!

Cordiali saluti.

+1

Grazie. Questo ha funzionato perfettamente e la tua risposta è stata quasi impossibile da trovare su Google, quindi consentimi di aggiungere alcune parole chiave. JAX-WS WSSE – Jimmy2Times

+1

Quando si utilizza questo codice ho ottenuto la seguente eccezione in log: 'com.sun.xml.internal.messaging.saaj.soap.impl.ElementImpl addChildElement SEVERE: SAAJ0101: Il padre di un SOAPBodyElement deve essere un SOAPBody'. – Vic

5

Se si implementa l'interfaccia SOAPHandler, il metodo msgCtx.getMessage() eseguirà il rendering dell'intero XML e, se si sta lavorando con file di grandi dimensioni, si avranno errori di memoria insufficiente. Ho provato con l'autenticazione UsernameToken sul client JAX-WS e funziona:

String SECURITY_NS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 
String PASSWORD_TYPE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"; 
String AUTH_PREFIX = "wss"; 

MyService service = new MyService(); 
MyServicePort port = service.getMyServicePort(); 

try { 
    SOAPFactory soapFactory = SOAPFactory.newInstance(); 
    SOAPElement security = soapFactory.createElement("Security", AUTH_PREFIX, SECURITY_NS); 
    SOAPElement uToken = soapFactory.createElement("UsernameToken", AUTH_PREFIX, SECURITY_NS); 
    SOAPElement username = soapFactory.createElement("Username", AUTH_PREFIX, SECURITY_NS); 
    username.addTextNode("username"); 

    SOAPElement pass = soapFactory.createElement("Password", AUTH_PREFIX, SECURITY_NS); 
    pass.addAttribute(new QName("Type"), PASSWORD_TYPE); 
    pass.addTextNode("password"); 

    uToken.addChildElement(username); 
    uToken.addChildElement(pass); 
    security.addChildElement(uToken); 

    Header header = Headers.create(security); 
    ((WSBindingProvider) port).setOutboundHeaders(header); 

    // now, call webservice 

} catch (SOAPException ex) { 
    ex.printStackTrace(); 
} 

Edit: si dovrebbe aggiungere il "rt.jar" da jre al classpath.

+0

L'ho provato, ma sto ottenendo javax.xml.ws.WebServiceException: java.lang.ClassCastException: non è possibile eseguire il cast di com.sun.xml.ws.message.DOMHeader su com.sun.xml.ws.security.opt.impl. outgoing.SecurityHeader \t a com.sun.xml.wss.jaxws.impl.SecurityClientTube.processRequest (SecurityClientTube.java:250) \t a com.sun.xml.ws.api.pipe.Fiber .__ doRun (Fiber.java : 1063) – Steve

+0

penso che sia correlato ad avere il vaso ws della metro nel classpath- ma ho bisogno di quello – Steve