首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在SOAP请求中添加头部?

如何在SOAP请求中添加头部?
EN

Stack Overflow用户
提问于 2013-01-25 21:40:51
回答 4查看 83.5K关注 0票数 20

我尝试通过java代码调用HTTPS SOAP web服务:

代码语言:javascript
复制
    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();

但却得到了异常:

代码语言:javascript
复制
threw an unexpected exception: javax.xml.ws.soap.SOAPFaultException: Security Requirements not met - No Security header in message

当我分析正确的请求样本时,我确定它必须包含头部:

代码语言:javascript
复制
 <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>

那么如何将这个头添加到我的SOAP请求中呢?

EN

回答 4

Stack Overflow用户

发布于 2013-01-25 22:34:49

我个人添加了两个类: HeaderHandler和HeaderHandlerResolver:

代码语言:javascript
复制
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.");
}
}

代码语言:javascript
复制
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;
   }
}

在HeaderHandler类中,可以添加所需的凭据。要最终使用它们:

代码语言:javascript
复制
HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver();
service.setHandlerResolver(handlerResolver);
票数 46
EN

Stack Overflow用户

发布于 2015-06-18 15:11:14

我遵循了@LaabidiRaissi提到的步骤。代码运行得很好,但是它从不在头下面附加安全元素。我已经通过将出站SOAP消息打印到System.out来确认这一点。经过深入研究,我发现需要显式保存SOAPMessage以反映更新后的消息头。

代码语言:javascript
复制
soapMessage.saveChanges();

有关更多参考信息- Check this link

票数 7
EN

Stack Overflow用户

发布于 2018-06-17 18:48:14

示例main类:

代码语言:javascript
复制
package test;

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

// next headers is generated from "NetBeans New Webservice Client"
import sk.firma.wstest.definitions.*;
import sk.firma.wstest.schemas.*;

/**
 *
 * @author Jan
 */
public class TestWSService {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        try {

            WsService service = new WsService();
            Ws port = service.getWsKsSoap11();

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

            // Initialize and Run Service
            InVal inVal = new InVal();
            ReturnValue retVal = port.test(inVal);

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

现在是WS-Security Header SOAP处理程序:

代码语言:javascript
复制
package test;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.TimeZone;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
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 WSSecurityHeaderSOAPHandler implements SOAPHandler<SOAPMessageContext> {

    private static final String URL_WSSE_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private static final String URL_WSU_NAMESPACE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";

    private final String usernameText;
    private final String passwordText;

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

    }

    public String getCurrentDateTime() {
        /* e.g. 2001-10-13T09:00:00Z */
        final SimpleDateFormat FORMATTER_DATETIME_NO_MS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

        DateFormat dfETC = FORMATTER_DATETIME_NO_MS;
        dfETC.setTimeZone(TimeZone.getTimeZone("CET"));

        StringBuffer dateETC = new StringBuffer(dfETC.format(new Date()));
        dateETC.append('Z');
        return dateETC.toString();
    }

    public String getCurrentDateTimePlusDelay(long delayInSeconds) {
        /* e.g. 2001-10-13T09:00:00Z */
        final SimpleDateFormat FORMATTER_DATETIME_NO_MS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");

        DateFormat dfETC = FORMATTER_DATETIME_NO_MS;
        dfETC.setTimeZone(TimeZone.getTimeZone("CET"));
        Date date = new Date();

        long timeInMsecs = date.getTime();
        date.setTime(timeInMsecs + delayInSeconds*1000L);
        StringBuffer dateETC = new StringBuffer(dfETC.format(date));
        dateETC.append('Z');
        return dateETC.toString();
    }

    @Override
    public boolean handleMessage(SOAPMessageContext soapMessageContext) {

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

        if (outboundProperty) {

            try {
                SOAPEnvelope soapEnvelope = soapMessageContext.getMessage().getSOAPPart().getEnvelope();

                SOAPHeader header = soapEnvelope.getHeader();
                if (header == null) {
                    header = soapEnvelope.addHeader();
                }

                SOAPElement securityHeaderElement = header.addChildElement("Security", "wsse", URL_WSSE_NAMESPACE);
                securityHeaderElement.addAttribute(soapEnvelope.createName("S:mustUnderstand"), "1");

                // Add Timestamp element to "Security" soapHeaderElement
                // Sample:  <u:Timestamp>
                //              <u:Created>2011-10-13T08:20:01.183Z</u:Created>
                //              <u:Expires>2011-10-13T17:25:01.183Z</u:Expires>
                //          </u:Timestamp>
                javax.xml.soap.Name timestampElementName = soapEnvelope.createName("Timestamp", "wsu", URL_WSU_NAMESPACE);
                SOAPElement timestampSOAPElement = securityHeaderElement.addChildElement(timestampElementName);
                String created = getCurrentDateTime(); 
                String expires = getCurrentDateTimePlusDelay(60L*60L); /* 60 minutes delay */

                // Add Created to Timestamp
                SOAPElement createdSOAPElement = timestampSOAPElement
                        .addChildElement("Created"/* local name */, "wsu" /* prefix */, URL_WSU_NAMESPACE);
                createdSOAPElement.addTextNode(created);

                // Add Expires to Timestamp
                SOAPElement expiresSOAPElement = timestampSOAPElement
                        .addChildElement("Expires"/* local name */, "wsu" /* prefix */,URL_WSU_NAMESPACE);
                expiresSOAPElement.addTextNode(expires);

                // Add usernameToken to "Security" soapHeaderElement
                javax.xml.soap.Name usernameTokenElementName = soapEnvelope.createName("UsernameToken", "wsse", 
                                            URL_WSSE_NAMESPACE);
                SOAPElement usernameTokenSOAPElement = securityHeaderElement.addChildElement(usernameTokenElementName);

                // Add Username to usernameToken
                SOAPElement userNameSOAPElement = usernameTokenSOAPElement
                        .addChildElement("Username"/* local name */, "wsse" /* prefix */, URL_WSSE_NAMESPACE);
                userNameSOAPElement.addTextNode(this.usernameText);

                // Add password to UsernameToken
                javax.xml.soap.Name passwordElementName = soapEnvelope.createName("Password", "wsse", URL_WSSE_NAMESPACE);
                SOAPElement passwordSOAPElement = usernameTokenSOAPElement.addChildElement(passwordElementName);

                /* Add "Type" attribute to <Password> header element */
                //passwordSOAPElement.addAttribute(soapEnvelope.createName("Type", "", ""), 
                //      "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
                passwordSOAPElement.addTextNode(this.passwordText);

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

        }

        return true;
    }

    @Override
    public void close(MessageContext context) {
        // TODO Auto-generated method stub
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public Set<QName> getHeaders() {
        // throw new UnsupportedOperationException("Not supported yet.");
        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;
    }

}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14522931

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档