Java/JAX-WS:调用 Web 服务在本地工作,但在 glassfish 上失败。身份验证问题 (SP0105)
我想做的是编写一段代码(部署在 glassfish 上的更大 Web 应用程序的一部分),通过 Web 服务连接到其他系统。但是我只编写客户端,所以我假设我无法更改 WSDL 或修改服务器端的任何内容(包括身份验证,这可能是这里的问题)。我是网络服务新手,所以请尽可能简单地写下您的答案。
我能够从 WSDL 生成类,编写连接到 Web 服务的简单命令行应用程序,添加安全标头(添加纯文本用户名/密码,更多内容见下文),调用一些方法并打印结果。在命令行上一切正常,但如果我将此代码附加到“更大的 webapp”(部署在 glassfish 上),我会收到以下错误:
SP0105:SymmetricBinding/AsymmetricBinding/TransportBinding 断言必须出现在 wsdl 中。
我没有从那里得到它 - 如果它可以从命令行(在 glassfish 之外)运行,为什么在部署到 glassfish 上时还需要更多东西?
我正在使用此页面中的提示: http ://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
为了提供更多信息,一些代码:
代码片段解析端点并调用服务(在文件 EndpointResolver.java 中):
URL baseUrl = EndpointResolver.class.getResource(".");
url = new URL(baseUrl, "WSDL_file.xml");
QName qname = new QName(SomeConfig.NAMESPACE, SomeConfig.LOCAL_PART);
Service service = Service.create(url, qname);
service.setHandlerResolver(headerHandlerResolver);
endpoint = service.getPort(MyPortType.class);
endpoint.doSomething();
//printing results here ..
HeaderHandlerResolver (实现 javax.xml.ws.handler.HandlerResolver) 最重要的方法:
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(headerHandler); //injected to HeaderHandlerResolver
return handlerChain;
}
HeaderHandler 处理方法(auth 在这里:) )
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("myUsername");
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("myPassword");
} catch (SOAPException e) {
log.warn(e.getMessage());
e.printStackTrace();
}
} else {
try {
//This handler does nothing with the response from the Web Service so
//we just print out the SOAP message.
logSOAPMessage(smc.getMessage());
} catch (Exception ex) {
log.warn(ex.getMessage());
ex.printStackTrace();
}
}
return outboundProperty;
}
@Override
public Set<QName> getHeaders() {
return null;
}
(...)
非常感谢您对此提供的任何帮助。
编辑: 以下是 wsdl 文件中的“策略”部分(如前所述,我无法更改):
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
What I want to do is to write a piece of code (part of bigger web-application deployed on glassfish) that connects to other system via webservice. However I'm writing client only, so I assume that I cannot change WSDL or modify anything on server side (including auth, that is probably a problem here). I'm new to webservices, so pretty please - write your answers as simple as they can be.
I was able to generate classes from WSDL, write simple command line application that connects to webservice, adds security header (add plaintext username/password, more below), calls some method and prints result. Everything works OK on command line, but if I'll attach this code to 'bigger webapp' (deploy on glassfish) I'm getting the following error:
SP0105: Either SymmetricBinding/AsymmetricBinding/TransportBinding assertion must be present in the wsdl.
I'm not getting it from there - if it works from command line (outside of glassfish), why does it need something more while deployed on glassfish?
I was using hints from this page:
http://www.javadb.com/using-a-message-handler-to-alter-the-soap-header-in-a-web-service-client
To give more info on this, some pieces of code:
Code fragment for resolving endpoint and calling service (in file EndpointResolver.java):
URL baseUrl = EndpointResolver.class.getResource(".");
url = new URL(baseUrl, "WSDL_file.xml");
QName qname = new QName(SomeConfig.NAMESPACE, SomeConfig.LOCAL_PART);
Service service = Service.create(url, qname);
service.setHandlerResolver(headerHandlerResolver);
endpoint = service.getPort(MyPortType.class);
endpoint.doSomething();
//printing results here ..
HeaderHandlerResolver (implementing javax.xml.ws.handler.HandlerResolver) most important methid:
public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerChain = new ArrayList<Handler>();
handlerChain.add(headerHandler); //injected to HeaderHandlerResolver
return handlerChain;
}
HeaderHandler handle method (auth is here :) )
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("myUsername");
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("myPassword");
} catch (SOAPException e) {
log.warn(e.getMessage());
e.printStackTrace();
}
} else {
try {
//This handler does nothing with the response from the Web Service so
//we just print out the SOAP message.
logSOAPMessage(smc.getMessage());
} catch (Exception ex) {
log.warn(ex.getMessage());
ex.printStackTrace();
}
}
return outboundProperty;
}
@Override
public Set<QName> getHeaders() {
return null;
}
(...)
Thank you very much for any help with this.
edit:
Below is 'policy' part from wsdl file (as stated before, I cannot change that):
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我将回答我自己的问题:
解决上述问题需要两件事。首先需要的是更新 glassfish 上的 Metro 库(我已将其更新到版本 2.1.1,因此更新了库 lib/webservices-rt.jar、lib/webservices-tools.jar、lib/endorsed/webservices-api 。罐)。这解决了 SP0105 错误,但生成了新的错误(标题中某处的 ClassCastException)。
为了解决第二个问题,我删除了 HeaderHandler/HeaderHandlerResolver 类,而不是:
调用:
I'll answer to my own question:
There were two things required to fix problem above. First thing that was required was to update metro library on glassfish (I've updated it to version 2.1.1, so updated libraries lib/webservices-rt.jar, lib/webservices-tools.jar, lib/endorsed/webservices-api.jar). That solved SP0105 error, but generated new one (ClassCastException somewhere at headers).
To fix the second one, I've deleted HeaderHandler/HeaderHandlerResolver classes and instead of:
called: