2015-02-12 17 views
11

Stiamo provando a eseguire un'implementazione di sicurezza nei nostri servizi Web JAX e stiamo passando l'UserName e la Password nell'intestazione come di seguito.Recupero dell'intestazione del sapone sul lato server JAXWS

<soapenv:Header> 
    <wsse:Security soapenv:mustUnderstand="0" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> 
     <wsse:UsernameToken wsu:Id="Id-8zvykuwmK8yg6dxn3632nQJB" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 
      <wsse:Username>gears_user</wsse:Username> 
      <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">##########</wsse:Password> 
     </wsse:UsernameToken> 
    </wsse:Security> 
</soapenv:Header> 

In Java Stiamo provando il recuperare il nome utente e la password, ma non siamo sicuri come farlo come, la sua parte di sapone Intestazione e non abbiamo recuperate le informazioni di intestazione prima.

..... 
    @Resource 
WebServiceContext wsctx; 


public ServiceAvailabilityResponseType inquireGeographicEligibility(ServiceAvailabilityRequestType inquireGeographicEligibilityRequest) 
    throws WSException 
{ 

    HeaderList hl=(HeaderList)wsctx.getMessageContext().get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY); 
    QName security = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", 
      "Security");  
    Header hd = hl.get(security, false); 


    QName userName = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", 
     "Username"); 
    try 
    { 
     System.out.println(hd.readHeader());  
     System.out.println(hd.getAttribute(userName)); 
    }catch (Exception e) { 
     System.out.println(e.getMessage()); 
    } 

    } 

che stiamo cercando di fare come sopra e ottenere gli elementi di intestazione, ma la sua non ci restituire il valore. Sarà gradito qualsiasi aiuto sul modo di recuperare Username e Password.

risposta

19

È possibile leggere l'intestazione soap da SOAPMessageContext in una classe SOAPHandler, quindi passare i valori all'implementazione @WebService tramite attributi nello MessageContext.

Mentre l'API HeaderList è specifica all'implementazione di riferimento JAX-WS, il seguente esempio deve essere portatile su qualsiasi runtime JAX-WS.

Esempio:

impl servizio Web:

package org.example.sampleservice; 

import javax.annotation.Resource; 
import javax.jws.HandlerChain; 
import javax.jws.WebService; 
import javax.xml.ws.WebServiceContext; 

@WebService(endpointInterface = "org.example.sampleservice.SampleService") 
@HandlerChain(file="handlers.xml") 
public class SampleServiceImpl implements SampleService { 

    @Resource 
    private WebServiceContext ctx; 

    @Override 
    public String sayHello(String name) { 
     String usernameFromHeader = (String) ctx.getMessageContext().get("USERNAME"); 
     return "Hello, " 
       + name 
       + " (invoked by " 
       + (usernameFromHeader == null ? "[err or no 'Security' header found]" 
         : usernameFromHeader) + ")"; 
    } 

} 

Handler catena XML (handlers.xml, un file nello stesso pacchetto come SampleServiceImpl.java):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<javaee:handler-chains 
    xmlns:javaee="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <javaee:handler-chain> 
    <javaee:handler> 
     <javaee:handler-class>org.example.sampleservice.UsernameTokenHandler</javaee:handler-class> 
    </javaee:handler> 
    </javaee:handler-chain> 
</javaee:handler-chains> 

Il JAX -Settore WS classe:

package org.example.sampleservice; 

import java.util.Iterator; 
import java.util.Set; 

import javax.xml.namespace.QName; 
import javax.xml.soap.Node; 
import javax.xml.soap.SOAPElement; 
import javax.xml.soap.SOAPHeader; 
import javax.xml.soap.SOAPHeaderElement; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.MessageContext.Scope; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 

public class UsernameTokenHandler implements SOAPHandler<SOAPMessageContext> { 

    private static final String WSSE_NS_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 
    private static final QName QNAME_WSSE_USERNAMETOKEN = new QName(WSSE_NS_URI, "UsernameToken"); 
    private static final QName QNAME_WSSE_USERNAME = new QName(WSSE_NS_URI, "Username"); 
    private static final QName QNAME_WSSE_PASSWORD = new QName(WSSE_NS_URI, "Password"); 

    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 

     Boolean outbound = (Boolean) context 
       .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
     if ((outbound != null) && (!outbound.booleanValue())) { 
      handleInboundMessage(context); 
     } 
     return true; 
    } 

    private void handleInboundMessage(SOAPMessageContext context) { 
     String wsseUsername = null; 
     String wssePassword = null; 
     try { 
      SOAPHeader header = context.getMessage().getSOAPHeader(); 
      Iterator<?> headerElements = header.examineAllHeaderElements(); 
      while (headerElements.hasNext()) { 
       SOAPHeaderElement headerElement = (SOAPHeaderElement) headerElements 
         .next(); 
       if (headerElement.getElementName().getLocalName() 
         .equals("Security")) { 
        SOAPHeaderElement securityElement = headerElement; 
        Iterator<?> it2 = securityElement.getChildElements(); 
        while (it2.hasNext()) { 
         Node soapNode = (Node) it2.next(); 
         if (soapNode instanceof SOAPElement) { 
          SOAPElement element = (SOAPElement) soapNode; 
          QName elementQname = element.getElementQName(); 
          if (QNAME_WSSE_USERNAMETOKEN.equals(elementQname)) { 
           SOAPElement usernameTokenElement = element; 
           wsseUsername = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_USERNAME); 
           wssePassword = getFirstChildElementValue(usernameTokenElement, QNAME_WSSE_PASSWORD); 
           break; 
          } 
         } 

         if (wsseUsername != null) { 
          break; 
         } 
        } 
       } 
       context.put("USERNAME", wsseUsername); 
       context.setScope("USERNAME", Scope.APPLICATION); 

       context.put("PASSWORD", wssePassword); 
       context.setScope("PASSWORD", Scope.APPLICATION); 
      } 
     } catch (Exception e) { 
      System.out.println("Error reading SOAP message context: " + e); 
      e.printStackTrace(); 
     } 

    } 

    private String getFirstChildElementValue(SOAPElement soapElement, QName qNameToFind) { 
     String value = null; 
     Iterator<?> it = soapElement.getChildElements(qNameToFind); 
     while (it.hasNext()) { 
      SOAPElement element = (SOAPElement) it.next(); //use first 
      value = element.getValue(); 
     } 
     return value; 
    } 

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

    @Override 
    public void close(MessageContext context) { 
    } 


    @Override 
    public Set<QName> getHeaders() { 
     return null; 
    } 

} 
+0

Ho svalutato questa risposta, ma poi ho capito che non funziona in ogni caso. Ora ho un validatore che implementa 'PasswordValidationCallback.PasswordValidator', e in questo caso' header.examineAllHeaderElements() 'restituisce un interator vuoto, come se non ci fossero nodi nell'intestazione,' getChildElements() 'fa lo stesso. Perché? Il validatore in qualche modo cancella l'intestazione dalla richiesta? – apcuk

Problemi correlati