Java 在JAXWS服务器端检索Soap头
我们正试图在JAX web服务中实现安全性,并在标题中传递用户名和密码,如下所示Java 在JAXWS服务器端检索Soap头,java,web-services,soap,jax-ws,Java,Web Services,Soap,Jax Ws,我们正试图在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=
<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>
我们正试图按照上面的方法获取header元素,但它并没有返回值。如果您在检索用户名和密码的过程中有任何帮助,我们将不胜感激。您可以在
SOAPHandler
类中从SOAPMessageContext
读取soap头,然后通过MessageContext
中的属性将值传递给@WebService
实现
尽管HeaderList
API特定于JAX-WS参考实现,但以下示例应该可以跨任何JAX-WS运行时移植
例如:
Web服务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) + ")";
}
}
处理程序链XML(handlers.XML,与SampleServiceImpl.java
位于同一个包中的文件):
org.example.sampleservice.UsernameTokenHandler
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;
}
}
package org.example.sampleservice;
导入java.util.Iterator;
导入java.util.Set;
导入javax.xml.namespace.QName;
导入javax.xml.soap.Node;
导入javax.xml.soap.SOAPElement;
导入javax.xml.soap.SOAPHeader;
导入javax.xml.soap.SOAPHeaderElement;
导入javax.xml.ws.handler.MessageContext;
导入javax.xml.ws.handler.MessageContext.Scope;
导入javax.xml.ws.handler.soap.SOAPHandler;
导入javax.xml.ws.handler.soap.SOAPMessageContext;
公共类UsernameTokenHandler实现SOAPHandler{
私有静态最终字符串WSSE_NS_URI=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
私有静态最终QName QName_WSSE_USERNAMETOKEN=新QName(WSSE_NS_URI,“USERNAMETOKEN”);
私有静态最终QName QName_WSSE_USERNAME=新QName(WSSE_NS_URI,“USERNAME”);
私有静态最终QName QName_WSSE_PASSWORD=新QName(WSSE_NS_URI,“密码”);
@凌驾
公共布尔handleMessage(SOAPMessageContext上下文){
布尔出站=(布尔)上下文
.get(MessageContext.MESSAGE\u出站\u属性);
如果((outbound!=null)&&(!outbound.booleanValue()){
handleInboundMessage(上下文);
}
返回true;
}
私有void handleInboundMessage(SOAPMessageContext上下文){
字符串wsseUsername=null;
字符串wssePassword=null;
试一试{
SOAPHeader=context.getMessage().getSOAPHeader();
迭代器headerElements=header.CheckeallheaderElements();
while(headerElements.hasNext()){
SOAPHeaderElement headerElement=(SOAPHeaderElement)headerElement
.next();
if(headerElement.getElementName().getLocalName()
.equals(“担保”)){
SOAPHeaderElement安全元素=headerElement;
迭代器it2=securityElement.getChildElements();
while(it2.hasNext()){
Node soapNode=(Node)it2.next();
if(SOAPElement的soapNode实例){
SOAPElement=(SOAPElement)soapNode;
QName elementQname=element.getElementQName();
if(QNAME_WSSE_USERNAMETOKEN.equals(elementQname)){
SOAPElement usernameTokenElement=元素;
wsseUsername=getFirstChildElementValue(usernameTokenElement,QNAME\u WSSE\u USERNAME);
wssePassword=getFirstChildElementValue(usernameTokenElement,QNAME\u WSSE\u密码);
打破
}
}
if(wsseUsername!=null){
打破
}
}
}
put(“用户名”,wsseUsername);
context.setScope(“用户名”,Scope.APPLICATION);
context.put(“密码”,wssePassword);
context.setScope(“密码”,Scope.APPLICATION);
}
}捕获(例外e){
System.out.println(“读取SOAP消息上下文时出错:+e”);
e、 printStackTrace();
}
}
私有字符串getFirstChildElementValue(SOAPElement SOAPElement,QName qNameToFind){
字符串值=null;
迭代器it=soapElement.getChildElements(qNameToFind);
while(it.hasNext()){
SOAPElement=(SOAPElement)it.next();//首先使用
value=element.getValue();
}
返回值;
}
@凌驾
公共布尔handleFault(SOAPMessageContext上下文){
返回false;
}
@凌驾
公共无效关闭(MessageContext上下文){
}
@凌驾
公共集getHeaders(){
返回null;
}
}
如果出现错误“MustUnderstand headers”,请重写getHeaders()
方法
@覆盖
公共集getHeaders(){
最终QName securityHeader=新QName(
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
“安全”,
“wsse”);
final HashSet headers=new HashSet();
headers.add(securityHeader);
//通知运行时已处理此问题
返回标题;
}
我对这个答案投了赞成票,但后来我意识到它并不适用于所有情况。现在我有一个验证器,它实现了PasswordValidationCallback.PasswordValidator
,在本例中是header.TesteallHeaderElements()
返回一个空的interator,就像在header中没有任何节点一样,getChildElements()
也执行相同的操作。为什么呢?验证器以某种方式从请求中删除了头?我很困惑,为什么我的项目找不到头
<?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>
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;
}
}
@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;
}