Java 在 JAXWS 服务器端检索 Soap 标头
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28487114/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retrieving Soap Header on JAXWS Server Side
提问by Suraj
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.
我们正在尝试在我们的 JAX Web 服务中进行安全实现,并在标头中传递用户名和密码,如下所示。
<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>
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.
在 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());
}
}
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.
我们正在尝试按照上述方法获取标题元素,但它没有返回值。任何有关检索用户名和密码的帮助将不胜感激。
采纳答案by Scott Heaberlin
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
.
你可以阅读从SOAP头SOAPMessageContext
的SOAPHandler
类,则值传递给你@WebService
通过在属性的实现MessageContext
。
Whereas the HeaderList
API is specific to the JAX-WS reference implementation, the following sample should be portable across any JAX-WS runtime.
尽管HeaderList
API 特定于 JAX-WS 参考实现,但以下示例应该可以跨任何 JAX-WS 运行时移植。
Example:
例子:
Web service 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 chain XML (handlers.xml, a file in the same package as SampleServiceImpl.java
):
处理程序链 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>
The JAX-WS handler class:
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;
}
}
回答by Chami
Override the getHeaders()
method if you're getting the error "MustUnderstand headers".
getHeaders()
如果您收到错误“MustUnderstand headers”,请覆盖该方法。
@Override
public Set<QName> getHeaders() {
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);
// notify the runtime that this is handled
return headers;
}