2016-06-21 172 views
1

对于这个问题,我真的可以做一些帮助,因为我已经连续几天将我的头撞到砖墙上了。Apache CXF策略异常(WS安全) - 无法检测到安全配置

我实现了使用Apache CXF一个非常简单的JAX-WS的服务,我想补充WS-SecurityPolicies加密和签名邮件正文但客户端,我发现了以下异常:

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> 

这是客户crypto.properties

org.apache.ws.security.crypto.merlin.keystore.file=client-keystore.jks 
org.apache.ws.security.crypto.merlin.keystore.password=client-pass 
org.apache.ws.security.crypto.merlin.keystore.private.password=key-pass 
org.apache.ws.security.crypto.merlin.keystore.alias=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> 

任何帮助将非常感激!

回答

0

设法让这一半利用工作,则下列

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()); 
2

我花了几天时间与Apache CXF 3.1.4解决这一问题和其他问题。事实是,CXF中的错误消息很少提供关于要修复的内容的真实线索。处于危险之中的人很典型:它讲述了一个没有找到的名字,但没有提供被查询的实际价值,其次,这不是我的情况中的问题。

我是从一个XML /基于Spring的CXF总线/策略配置测试和督促工作了一年开始,像:

SpringBusFactory bf = new SpringBusFactory(); 
URL busFile = MyClient.class.getResource("/wssec_policy.xml"); 
Bus bus = bf.createBus(busFile); 
BusFactory.setDefaultBus(bus); 

其中wssec_policy.xml包含JAXWS:客户机定义如下所示:

​​

并且其中加密和signature.properties包含WSS4J properties

我的挑战只是为了在JRE 8上使用CXF 3.1.4,BouncyCastle 1.52,Spring 4.2.4;哪一个没有,首先就你引用的错误敲响。

我在POJO客户端组装了代码,并开始在CXF源代码中进行钻取以找到真正原因,并发现上述默认总线设置(以前没有工作)不再提供jaxws:client meta-数据到WSS4J层。没有数据,因此错误。 Apache CXF提供了三种配置WS- *堆栈的方法(显式拦截器,基于策略的XML和基于策略的Java API)。 为了解决您的问题,我通过Java API切换到基于策略的配置如下:曾经需要

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"); 

最后两个属性在调试进步,解决错误的密钥长度错误由于缺少关键别名!但最后,我注意到它没有它们就回来了! (它们实际上复制Client_Encrypt和Client_Sign属性中的密钥库别名)。

然后我解决了没有发现加密的证书错误通过禁止“org.apache.ws.security.crypto.merlin.keystore。供应商= BC”从Client_Encrypt和Client_Sign属性(在过去的版本还没有工作)。

我解决PKCS12密钥库类型JKS切换缺少证书错误。我发现keystore.load()不取所包含的所有证书......以相同的密钥库P12得到我根据上下文不同的结局,它叫...越野车确实如此。

我解决AsymmetricBinding不通过观察支持的在现场服务器重新部署(在我的情况下JBoss EAP7)从来没有工作,但何时已部署的应用程序随服务器一起启动(因此在服务器重启后),它可以正常工作。我强烈怀疑类加载器问题。

让我补充一点,我曾经切换回JRE 7(遗留运行正常),错误显着不同(我怀疑JRE中的策略配置文件)。

另一个主要困难是所有的错误,无论是客户端处理请求甚至响应以及服务器端错误的异常,都被CXF包装为带有简明错误消息的soap错误,这使得它非常难以了解真正发生的事情。让我进步的唯一方法是在POJO中汇编所需的客户端代码,并在CXF和WSS4J源代码库的帮助下进行调试(Eclipse/Maven在使用调试器的同时获取源代码并向下钻取...高效!)