2015-02-12 7 views
11

Wir versuchen, eine Sicherheitsimplementierung in unseren JAX-Webdiensten durchzuführen und übergeben den Benutzernamen und das Passwort in der Kopfzeile wie folgt.Abrufen von Soap-Header auf der JAXWS-Serverseite

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

Im Java wir versuchen, die den Benutzernamen und das Passwort abrufen, aber wir nicht sicher sind, wie es zu tun, wie, es ist ein Teil von SOAP-Header und wir haben Header-Informationen nicht vor abgerufen.

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

    } 

Wir versuchen, wie oben zu tun und erhalten die Header-Elemente, aber es gibt uns nicht den Wert zurück. Jede Hilfe auf dem Weg, den Benutzernamen und das Passwort zu erhalten, wird geschätzt.

Antwort

19

Sie können den Soap-Header aus der SOAPMessageContext-Klasse in einer SOAPHandler-Klasse lesen und die Werte dann über die Attribute in MessageContext an Ihre @WebService-Implementierung übergeben.

Während die HeaderList-API spezifisch für die JAX-WS-Referenzimplementierung ist, sollte das folgende Beispiel über jede JAX-WS-Laufzeit hinweg portierbar sein.

Beispiel:

Webdienst impl:

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 Kette XML (handlers.xml, eine Datei im selben Paket wie 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> 

Die JAX -WS-Handler-Klasse:

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

Ich habe diese Antwort hochgestuft, aber dann habe ich festgestellt, dass es nicht in jedem Fall funktioniert. Nun habe ich einen Validator, der 'PasswordValidationCallback.PasswordValidator' implementiert, und in diesem Fall gibt' header.examineAllHeaderElements() '' einen leeren Interator zurück, als ob es keine Knoten in der Kopfzeile gäbe, 'getChildElements()' macht das gleiche. Warum das? Der Validierer löscht den Header irgendwie aus der Anfrage? – apcuk

Verwandte Themen