我们正在尝试在我们的JAX Web服务中执行安全性实现,并且在标题中传递UserName和Password,如下所示.
<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的一部分,我们之前没有检索到头信息.
..... @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()); } }
解决方法
您可以从SOAPHandler类中的SOAPMessageContext读取soap头,然后通过MessageContext中的属性将值传递给您的@WebService实现.
而HeaderList API特定于JAX-WS参考实现,以下示例应该在任何JAX-WS运行时都可移植.
例:
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相同的包中的文件):
<?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处理程序类:
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; } }