2016-06-21 41 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在使用調試器的同時獲取源代碼並向下鑽取...高效!)