2013-01-25 21 views
17

tôi cố gắng gọi dịch vụ web SOAP HTTPS thông qua mã java:Cách thêm tiêu đề vào yêu cầu SOAP?

URL url = new URL("https://somehost:8181/services/"SomeService?wsdl"); 
    QName qname = new QName("http://services.somehost.com/", "SomeService"); 
    Service service = Service.create(url, qname); 
    SomeService port = service.getPort(SomeService .class); 
    port.doSomething(); 

Nhưng có được ngoại lệ:

threw an unexpected exception: javax.xml.ws.soap.SOAPFaultException: Security Requirements not met - No Security header in message 

Khi tôi analized mẫu yêu cầu đúng tôi xác định nó phải chứa tiêu đề:

<S:Header> 
    <To xmlns="http://www.w3.org/2005/08/addressing">http://somehost:8181/services/SomeService</To> 
    <Action xmlns="http://www.w3.org/2005/08/addressing">https://somehost:8181/services/"SomeService/doSomethingRequest</Action> 
    <ReplyTo xmlns="http://www.w3.org/2005/08/addressing"> 
    <Address>http://www.w3.org/2005/08/addressing/anonymous</Address> 
    </ReplyTo> 
    <MessageID xmlns="http://www.w3.org/2005/08/addressing">uuid:3428539e-d645-72ae-adc0-5423c1e68942</MessageID> 
    <wsse:Security S:mustUnderstand="true"> 
    <wsu:Timestamp wsu:Id="_1" xmlns:ns14="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:ns13="http://schemas.xmlsoap.org/soap/envelope/"> 
     <wsu:Created>2013-01-15T16:36:30Z</wsu:Created> 
     <wsu:Expires>2014-01-15T14:06:30Z</wsu:Expires> 
    </wsu:Timestamp> 
    </wsse:Security> 

Vậy làm cách nào để thêm tiêu đề này vào yêu cầu SOAP của tôi?

Trả lời

35

Cá nhân tôi thêm hai lớp: HeaderHandler và HeaderHandlerResolver:

import java.util.HashSet; 
import java.util.Set; 

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


public class HeaderHandler implements SOAPHandler<SOAPMessageContext> { 

public boolean handleMessage(SOAPMessageContext smc) { 

    Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 

    if (outboundProperty.booleanValue()) { 

     SOAPMessage message = smc.getMessage(); 

     try { 

      SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope(); 
      SOAPHeader header = envelope.addHeader(); 

      SOAPElement security = 
        header.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 



      SOAPElement usernameToken = 
        security.addChildElement("UsernameToken", "wsse"); 
      usernameToken.addAttribute(new QName("xmlns:wsu"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); 

      SOAPElement username = 
        usernameToken.addChildElement("Username", "wsse"); 
      username.addTextNode("test"); 

      SOAPElement password = 
        usernameToken.addChildElement("Password", "wsse"); 
      password.setAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"); 
      password.addTextNode("test321"); 

      //Print out the outbound SOAP message to System.out 
      message.writeTo(System.out); 
      System.out.println(""); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

    } else { 
     try { 

      //This handler does nothing with the response from the Web Service so 
      //we just print out the SOAP message. 
      SOAPMessage message = smc.getMessage(); 
      message.writeTo(System.out); 
      System.out.println(""); 

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


    return outboundProperty; 

} 

public Set getHeaders() { 
    // The code below is added on order to invoke Spring secured WS. 
    // Otherwise, 
    // http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd 
    // won't be recognised 
    final QName securityHeader = new QName(
      "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", 
      "Security", "wsse"); 

    final HashSet headers = new HashSet(); 
    headers.add(securityHeader); 

    return headers; 
} 

public boolean handleFault(SOAPMessageContext context) { 
    //throw new UnsupportedOperationException("Not supported yet."); 
    return true; 
} 

public void close(MessageContext context) { 
//throw new UnsupportedOperationException("Not supported yet."); 
} 
} 

import java.util.ArrayList; 
import java.util.List; 
import javax.xml.ws.handler.Handler; 
import javax.xml.ws.handler.HandlerResolver; 
import javax.xml.ws.handler.PortInfo; 


public class HeaderHandlerResolver implements HandlerResolver { 

public List<Handler> getHandlerChain(PortInfo portInfo) { 
    List<Handler> handlerChain = new ArrayList<Handler>(); 

    HeaderHandler hh = new HeaderHandler(); 

    handlerChain.add(hh); 

    return handlerChain; 
    } 
} 

Trong lớp HeaderHandler, bạn có thể thêm các thông tin cần thiết. Để sử dụng chúng cuối cùng:

HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver(); 
service.setHandlerResolver(handlerResolver); 
+0

Đây là chính xác những gì tôi đang tìm kiếm. Cảm ơn bạn cho ví dụ kỹ lưỡng của bạn. –

+0

bạn được chào đón –

+0

cảm ơn bạn rất nhiều. bạn đã cứu cả ngày sắp tới của tôi! –

5

Tôi đã làm theo các bước được đề cập bởi @LaabidiRaissi. Mã hoạt động tốt nhưng nó không bao giờ nối thêm phần tử bảo mật dưới tiêu đề. Tôi đã xác nhận nó bằng cách in ra thông báo SOAP gửi đi tới System.out. Sau khi nghiên cứu sâu, tôi đã thấy rằng SOAPMessage cần phải được lưu một cách rõ ràng để phản ánh tiêu đề thư được cập nhật.

soapMessage.saveChanges(); 

Để tham khảo hơn - Check this link

+0

Mã từ câu trả lời của @ Laabidi được sử dụng để làm việc cho tôi với Java 7 và tomcat 7. Sau khi nâng cấp lên Java 8 và tomcat 8 soapMessage.saveChanges() là cần thiết. – Hok

1

Bạn cũng có thể sử dụng Apache WSS4J để dễ dàng thêm các header và còn mã hóa bạn mật khẩu.

import org.apache.ws.security.WSConstants; 
import org.apache.ws.security.message.WSSecHeader; 
import org.apache.ws.security.message.WSSecUsernameToken; 

import javax.xml.namespace.QName; 
import javax.xml.soap.SOAPMessage; 
import javax.xml.soap.SOAPPart; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 
import java.io.ByteArrayOutputStream; 
import java.util.Set; 

public class WSSecurityHeaderSOAPHandler implements SOAPHandler<SOAPMessageContext> { 


    private final String usernameText; 
    private final String passwordText; 

    public WSSecurityHeaderSOAPHandler(String usernameText, String passwordText) { 
     this.usernameText = usernameText; 
     this.passwordText = passwordText; 
    } 

    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 

     if (outboundProperty.booleanValue()) { 

      try { 
       SOAPMessage soapMessage = context.getMessage(); 
       soapMessage.removeAllAttachments(); 

       SOAPPart soappart = soapMessage.getSOAPPart(); 
       WSSecHeader wsSecHeader = new WSSecHeader(); 
       wsSecHeader.insertSecurityHeader(soappart); 
       WSSecUsernameToken token = new WSSecUsernameToken(); 
       token.setPasswordType(WSConstants.PASSWORD_DIGEST); 
       token.setUserInfo(usernameText, passwordText); 
       token.build(soappart, wsSecHeader); 

       soapMessage.saveChanges(); 
      } catch (Exception e) { 
       throw new RuntimeException("Error on wsSecurityHandler: " + e.getMessage()); 
      } 

     } 

     return true; 
    } 

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

    @Override 
    public void close(MessageContext context) { 

    } 

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

Và bạn cần cập nhật yêu cầu của bạn như thế này:

// This is the block that apply the Ws Security to the request 
BindingProvider bindingProvider = (BindingProvider) portType; 
List<Handler> handlerChain = new ArrayList<>(); 
handlerChain.add(new WSSecurityHeaderSOAPHandler("username", "password")); 
bindingProvider.getBinding().setHandlerChain(handlerChain); 

Maven phụ thuộc:

 <dependency> 
      <groupId>org.apache.ws.security</groupId> 
      <artifactId>wss4j</artifactId> 
      <version>1.6.19</version> 
     </dependency>