Java Apache CXF策略异常(WS-Security)-无法检测到安全配置
这真的需要一些帮助,因为我已经用头撞砖墙好几天了 我已经使用ApacheCXF实现了一个非常简单的JAX-WS服务,我正在尝试添加WS-SecurityPolicys来加密和签名消息体,但是客户端我遇到了以下异常:Java Apache CXF策略异常(WS-Security)-无法检测到安全配置,java,soap,cxf,jax-ws,ws-security,Java,Soap,Cxf,Jax Ws,Ws Security,这真的需要一些帮助,因为我已经用头撞砖墙好几天了 我已经使用ApacheCXF实现了一个非常简单的JAX-WS服务,我正在尝试添加WS-SecurityPolicys来加密和签名消息体,但是客户端我遇到了以下异常: org.apache.cxf.ws.policy.PolicyException: Security configuration could not be detected. Potential cause: Make sure jaxws:client element with n
org.apache.cxf.ws.policy.PolicyException: Security configuration could not be detected. Potential cause: Make sure jaxws:client element with name attribute value matching endpoint port is defined as well as a security.signature.properties element within it.
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractCommonBindingHandler.unassertPolicy(AbstractCommonBindingHandler.java:92)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getSignatureBuilder(AbstractBindingBuilder.java:1797)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignature(AsymmetricBindingHandler.java:693)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:171)
at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:110)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessageInternal(PolicyBasedWSS4JOutInterceptor.java:190)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:109)
at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:96)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:277)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:139)
这是我的applicationContext.xml客户端:
<bean id="passwordCallback"
class="com.example.payment.engine.soap.service.ClientPasswordCallback"></bean>
<jaxws:client
name="{http://service.soap.engine.payment.example.com/}HelloWorldImplService"
createdFromAPI="true" id="helloClient"
serviceClass="com.example.payment.engine.soap.service.HelloWorld"
address="http://localhost:8080/payment-engine/api/soap/hello">
<jaxws:properties>
<entry key="ws-security.callback-handler" value-ref="passwordCallback" />
<entry key="ws-security.encryption.properties" value="crypto.properties" />
<entry key="ws-security.signature.properties" value="crypto.properties" />
<entry key="ws-security.encryption.username" value="server" />
</jaxws:properties>
</jaxws:client>
最后是WSDL:
<wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:tns="http://service.soap.engine.payment.example.com/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:ns1="http://schemas.xmlsoap.org/soap/http" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" name="HelloWorldImplService"
targetNamespace="http://service.soap.engine.payment.example.com/">
<wsdl:types>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://service.soap.engine.payment.example.com/"
elementFormDefault="unqualified" targetNamespace="http://service.soap.engine.payment.example.com/" version="1.0">
<xs:element name="sayHello" type="tns:sayHello" />
<xs:element name="sayHelloResponse" type="tns:sayHelloResponse" />
<xs:complexType name="sayHello">
<xs:sequence />
</xs:complexType>
<xs:complexType name="sayHelloResponse">
<xs:sequence>
<xs:element minOccurs="0" name="return" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
</wsdl:types>
<wsdl:message name="sayHelloResponse">
<wsdl:part element="tns:sayHelloResponse" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:message name="sayHello">
<wsdl:part element="tns:sayHello" name="parameters"></wsdl:part>
</wsdl:message>
<wsdl:portType name="HelloWorld">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello" name="sayHello"></wsdl:input>
<wsdl:output message="tns:sayHelloResponse" name="sayHelloResponse"></wsdl:output>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="HelloWorldImplServiceSoapBinding" type="tns:HelloWorld">
<wsp:PolicyReference URI="#HelloWorldBindingPolicy"/>
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="sayHello">
<soap:operation soapAction="" style="document" />
<wsdl:input name="sayHello">
<wsp:PolicyReference URI="#HelloWorldInputBindingPolicy" />
<soap:body use="literal" />
</wsdl:input>
<wsdl:output name="sayHelloResponse">
<wsp:PolicyReference URI="#HelloWorldOutputBindingPolicy" />
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="HelloWorldImplService">
<wsdl:port binding="tns:HelloWorldImplServiceSoapBinding" name="HelloWorldImplPort">
<soap:address location="http://localhost:8080/payment-engine/api/soap/hello" />
</wsdl:port>
</wsdl:service>
<wsp:Policy wsu:Id="HelloWorldBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssX509V3Token11 />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
<wsp:Policy>
<sp:WssX509V3Token11 />
<sp:RequireIssuerSerialReference />
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
<sp:Layout>
<wsp:Policy>
<sp:Strict />
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp />
<sp:OnlySignEntireHeadersAndBody />
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128 />
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:EncryptSignature />
</wsp:Policy>
</sp:AsymmetricBinding>
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefIssuerSerial />
</wsp:Policy>
</sp:Wss11>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="HelloWorldInputBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body />
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="HelloWorldOutputBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<sp:EncryptedParts>
<sp:Body />
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body />
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</wsdl:definitions>
任何帮助都将不胜感激 通过使用以下方法,成功地完成了这一半
HelloWorldImplService service = new HelloWorldImplService();
HelloWorld port = service.getHelloWorldImplPort();
Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.put("ws-security.callback-handler", "com.example.payment.engine.soap.service.ClientPasswordCallback");
ctx.put("ws-security.encryption.properties", "config/crypto.properties");
ctx.put("ws-security.signature.properties", "config/crypto.properties");
ctx.put("ws-security.encryption.username", "server");
System.out.println(port.sayHello());
HelloWorldImplService=new HelloWorldImplService();
HelloWorld端口=服务。getHelloWorldImplPort();
映射ctx=((BindingProvider)端口).getRequestContext();
put(“ws-security.callback处理程序”、“com.example.payment.engine.soap.service.ClientPasswordCallback”);
ctx.put(“ws-security.encryption.properties”、“config/crypto.properties”);
ctx.put(“ws-security.signature.properties”、“config/crypto.properties”);
ctx.put(“ws-security.encryption.username”、“server”);
System.out.println(port.sayHello());
通过使用以下方法,成功地完成了这一半
HelloWorldImplService service = new HelloWorldImplService();
HelloWorld port = service.getHelloWorldImplPort();
Map<String, Object> ctx = ((BindingProvider) port).getRequestContext();
ctx.put("ws-security.callback-handler", "com.example.payment.engine.soap.service.ClientPasswordCallback");
ctx.put("ws-security.encryption.properties", "config/crypto.properties");
ctx.put("ws-security.signature.properties", "config/crypto.properties");
ctx.put("ws-security.encryption.username", "server");
System.out.println(port.sayHello());
HelloWorldImplService=new HelloWorldImplService();
HelloWorld端口=服务。getHelloWorldImplPort();
映射ctx=((BindingProvider)端口).getRequestContext();
put(“ws-security.callback处理程序”、“com.example.payment.engine.soap.service.ClientPasswordCallback”);
ctx.put(“ws-security.encryption.properties”、“config/crypto.properties”);
ctx.put(“ws-security.signature.properties”、“config/crypto.properties”);
ctx.put(“ws-security.encryption.username”、“server”);
System.out.println(port.sayHello());
我花了几天时间解决Apache CXF 3.1.4的这个问题和其他问题。事实上,CXF中的错误消息很少提供关于修复内容的真正线索。这个问题非常典型:它讲述了一个未找到的名称,但没有提供实际查找的值;其次,在我的上下文中,这不是问题所在
我从一个基于XML/Spring的CXF总线/策略配置开始,在test和prod中工作了一年多,诸如此类:
SpringBusFactory bf = new SpringBusFactory();
URL busFile = MyClient.class.getResource("/wssec_policy.xml");
Bus bus = bf.createBus(busFile);
BusFactory.setDefaultBus(bus);
其中wssec_policy.xml包含jaxws:client定义,如下所示:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="...etc...">
<bean id="logOutbound" class="MyLoggingOutInterceptor"/>
<bean id="logInbound" class="MyLoggingInInterceptor"/>
<cxf:bus>
<cxf:outInterceptors><ref bean="logOutbound"/></cxf:outInterceptors>
<cxf:inInterceptors><ref bean="dumpMessageInterceptor"/><ref bean="logInbound"/></cxf:inInterceptors>
<cxf:features><cxf:logging/></cxf:features>
</cxf:bus>
<jaxws:client name="{http://some.domain/webservices}servicioSoap" createdFromAPI="true">
<jaxws:properties>
<entry key="security.encryption.properties" value="etc/Client_Encrypt.properties"/>
<entry key="security.signature.properties" value="etc/Client_Sign.properties"/>
</jaxws:properties>
</jaxws:client>
</beans>
serviceGDS = new WSDL2Java_generated_Service();
portGDS = serviceGDS.getServiceGdsSoap();
Map<String, Object> ctx = ((javax.xml.ws.BindingProvider)portGDS).getRequestContext();
Properties encProps = new Properties();
encProps.load(new FileInputStream("etc/Client_Encrypt.properties"));
ctx.put("security.encryption.properties", encProps);
Properties signProps = new Properties();
signProps.load(new FileInputStream("etc/Client_Sign.properties"));
ctx.put("security.signature.properties", signProps);
// setting the props below once helped solving the error at stake
ctx.put("security.signature.username","test_keypair");
ctx.put("security.encryption.username","gds_test_cert");
以及encryption和signature.properties包含的位置
我的挑战是让它在JRE 8上与CXF 3.1.4、BouncyCastle 1.52、Spring 4.2.4一起工作;但事实并非如此,首先是你所引用的错误
我在一个POJO客户机中组装了代码,并开始深入研究CXF源代码,以找到真正的原因,并发现上面的默认总线设置(以前确实有效)不再向WSS4J层提供jaxws:client元数据。没有数据,因此出现错误。Apache CXF提供了三种配置WS-*堆栈的方法(显式拦截器、基于XML的策略和通过Java API基于策略)。
为了解决您的问题,我通过java API切换到基于策略的配置,如下所示:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:cxf="http://cxf.apache.org/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" xsi:schemaLocation="...etc...">
<bean id="logOutbound" class="MyLoggingOutInterceptor"/>
<bean id="logInbound" class="MyLoggingInInterceptor"/>
<cxf:bus>
<cxf:outInterceptors><ref bean="logOutbound"/></cxf:outInterceptors>
<cxf:inInterceptors><ref bean="dumpMessageInterceptor"/><ref bean="logInbound"/></cxf:inInterceptors>
<cxf:features><cxf:logging/></cxf:features>
</cxf:bus>
<jaxws:client name="{http://some.domain/webservices}servicioSoap" createdFromAPI="true">
<jaxws:properties>
<entry key="security.encryption.properties" value="etc/Client_Encrypt.properties"/>
<entry key="security.signature.properties" value="etc/Client_Sign.properties"/>
</jaxws:properties>
</jaxws:client>
</beans>
serviceGDS = new WSDL2Java_generated_Service();
portGDS = serviceGDS.getServiceGdsSoap();
Map<String, Object> ctx = ((javax.xml.ws.BindingProvider)portGDS).getRequestContext();
Properties encProps = new Properties();
encProps.load(new FileInputStream("etc/Client_Encrypt.properties"));
ctx.put("security.encryption.properties", encProps);
Properties signProps = new Properties();
signProps.load(new FileInputStream("etc/Client_Sign.properties"));
ctx.put("security.signature.properties", signProps);
// setting the props below once helped solving the error at stake
ctx.put("security.signature.username","test_keypair");
ctx.put("security.encryption.username","gds_test_cert");
serviceGDS=新的WSDL2Java_生成的_服务();
portGDS=serviceGDS.getServiceGdsSoap();
Map ctx=((javax.xml.ws.BindingProvider)portGDS.getRequestContext();
Properties encProps=新属性();
加载(新文件输入流(“etc/Client_Encrypt.properties”);
ctx.put(“security.encryption.properties”,encProps);
Properties signProps=新属性();
加载(新文件输入流(“etc/Client_Sign.properties”);
ctx.put(“security.signature.properties”,signProps);
//设置下面的道具曾经有助于解决关键的错误
ctx.put(“安全性、签名、用户名”、“测试密钥对”);
ctx.put(“security.encryption.username”、“gds_test_cert”);
最后两个属性曾经是进行调试所必需的,解决了由于缺少密钥别名而导致的错误密钥长度错误!!!日分