我正在尝试创建第三方WS的客户端。我的应用程序在JBoss AS 6上运行(带有Apache CXF 2.3.1堆栈)。我通过wsconsume(wsdl2java)生成了客户端代码。当我尝试连接到WS时出现异常:
No assertion builder for type http://schemas.microsoft.com/ws/06/2004/policy/http}BasicAuthentication registered.
Exception in thread "main" org.apache.cxf.ws.policy.PolicyException: None of the policy alternatives can be satisfied.
WSDL的Auth部分看起来像:
<wsp:Policy wsu:Id="abc_ssl_policy">
<wsp:ExactlyOne>
<wsp:All>
<http:BasicAuthentication
xmlns:http="http://schemas.microsoft.com/ws/06/2004/policy/http" />
<sp:TransportBinding
xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false" />
</wsp:Policy>
</sp:TransportToken>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic256 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
</wsp:Policy>
</sp:TransportBinding>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
客户代码:
@WebServiceClient(name = "Abc",
wsdlLocation = "https://hiddendomain.com/abc/abc.svc?wsdl",
targetNamespace = "http://tempuri.org/")
public class Abc extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://tempuri.org/", "Abc");
public final static QName AbcSsl = new QName("http://tempuri.org/", "abc_ssl");
static {
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("user", "pas".toCharArray());
}
});
URL url = null;
try {
url = new URL("https://hiddendomain.com/abc/abc.svc?wsdl");
} catch (MalformedURLException e) {
java.util.logging.Logger.getLogger(DistrInfo.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "...");
}
WSDL_LOCATION = url;
}
当我尝试使用Conduit时抛出异常:
Client client = ClientProxy.getClient(port);
HTTPConduit con = (HTTPConduit) client.getConduit(); <- exception
我怀疑这是因为非标准的MS策略,我需要适当的Intercerptor来处理这个策略,但有人可以告诉我一个怎么做的方法吗?
我甚至不,我应该把我的HTTPS凭据放到auth(我无法获得管道)
答案 0 :(得分:12)
使用此代码时问题消失了:
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
...
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
//factory.getInInterceptors().add(new LoggingInInterceptor());
//factory.getOutInterceptors().add(new LoggingOutInterceptor());
factory.setServiceClass(IAbc.class);
factory.setAddress("https://hiddendomain.com/abc/abc.svc/soap"); <- must be /soap there, otherwise 404
IAbc info = (IAbc) factory.create();
Client client = ClientProxy.getClient(info);
HTTPConduit http = (HTTPConduit) client.getConduit();
http.getAuthorization().setUserName("user");
http.getAuthorization().setPassword("pass");
String abc = info.abc();
答案 1 :(得分:1)
你太棒了。这解决了我的wsse问题:我的wsdl中的策略安全问题。现在我可以使用CXF调用安全服务。
我需要在我的代码中添加以下内容
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(TicketServicePortType.class);
factory.setAddress("http://localhost:8090/services");
TicketServicePortType port = (TicketServicePortType) factory.create();
Client client = ClientProxy.getClient(port);
HTTPConduit http = (HTTPConduit) client.getConduit();
http.getAuthorization().setUserName("user");
http.getAuthorization().setPassword("password");
Endpoint cxfEndpoint = client.getEndpoint();
Map<String,Object> outProps = new HashMap<String,Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, "user");
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,
ClientPasswordCallback.class.getName());
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps);
cxfEndpoint.getOutInterceptors().add(wssOut);
答案 2 :(得分:1)
我立即帮助从项目中移除 cxf-bundle :
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-bundle</artifactId>
<version>2.7.17</version>
</dependency>