本文介绍了在 JAXWS 服务器端检索 Soap 标头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试在我们的 JAX 网络服务中进行安全实现,并在标头中传递用户名和密码,如下所示.

We are trying to do a security implementation in our JAX web services and are passing the UserName and Password in the header as below.

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

在 Java 中,我们正在尝试检索用户名和密码,但我们不知道该怎么做,因为它是 Soap Header 的一部分,我们之前没有检索过标题信息.

In the Java we are trying the retrieve the Username and the password but we are not sure how to do it as, its a part of Soap Header and we have not retrieved header information before.

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

   }

我们正在尝试按照上述方法获取标题元素,但它没有返回值.任何有关检索用户名和密码的帮助将不胜感激.

We are trying to do as above and get the header elements but its not returning us the value. Any help on the way to retrieve the Username and Password will be appreciated.

推荐答案

您可以从 SOAPHandler 类中的 SOAPMessageContext 读取soap 标头,然后将值传递给您通过 MessageContext 中的属性实现 @WebService.

You can read the soap header from the SOAPMessageContext in a SOAPHandler class, then pass the values to your @WebService implementation via attributes in the MessageContext.

虽然 HeaderList API 特定于 JAX-WS 参考实现,但以下示例应该可以跨任何 JAX-WS 运行时移植.

Whereas the HeaderList API is specific to the JAX-WS reference implementation, the following sample should be portable across any JAX-WS runtime.

示例:

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) + ")";
    }

}

处理程序链 XML(handlers.xml,与 SampleServiceImpl.java 在同一个包中的文件):

Handler chain XML (handlers.xml, a file in the same package as 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>

JAX-WS 处理程序类:

The JAX-WS handler class:

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

}

这篇关于在 JAXWS 服务器端检索 Soap 标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 20:34