在没有属性文件的情况下在 MULE 中设置 WS-Security(WSS4JInInterceptor with signaturePropRefId)

Setting up WS-Security in MULE without properties file (WSS4JInInterceptor with signaturePropRefId)

我正在尝试在 CXF Proxy MULE 项目中设置 WS-Security。我目前正在使用属性文件,但我想从属性文件中取出一些信息并将其插入数据库,以便在那里可以保护它,但我找不到使其工作的方法。

我项目中的相关数据现在是这样的:

流中的 CXF 代理:

<cxf:proxy-service  doc:name="CXF Server" wsdlLocation="${wss.http.protocol}://${wss.http.host}:${wss.http.port}${wss.http.base_path}?${wss.http.wsdl_file}"  payload="envelope" bindingId="${wss.http.binding_id}" namespace="${wss.http.namespace}" service="${wss.http.service}" >
    <cxf:inInterceptors>
        <spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
        <spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
            <spring:constructor-arg>
                <spring:map>
                    <spring:entry key="action" value="Signature" />
                    <spring:entry key="signaturePropFile" value="ws.properties" />
                </spring:map>
            </spring:constructor-arg>
        </spring:bean>
    </cxf:inInterceptors>
</cxf:proxy-service>

ws.properties 文件:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=JKS
org.apache.ws.security.crypto.merlin.file=myTrustStore.jks
org.apache.ws.security.crypto.merlin.keystore.password=myTrustStorePass

我需要从项目文件中取出这些文件和 keystore.password 参数,然后将它们设置在数据库中以便注入。

我徒劳地(因为像 util:properties 这样的标签会抛出 'The prefix "util" for element "util:properties" is not bound' 错误)尝试了一种类似于此处显示的方法: http://cxf.547215.n5.nabble.com/WS-Security-Properties-Reference-td5505704.html

我也试过以这种方式设置属性文件,以便从 BD 获取相关数据,但是这些数据没有被注入:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=JKS
org.apache.ws.security.crypto.merlin.file=${wss.trustKeystore.file}
org.apache.ws.security.crypto.merlin.keystore.password=${wss.trustKeystore.password}

我做错了什么吗? 这可以通过任何公开的方式(或任何其他方式)解决吗?如果可以,怎么做?

谢谢。

由于此问题的新方案而编辑:

当我从属性文件加载拦截器的配置时,一切正常,但我需要从数据库中注入这些配置属性,所以我决定使用 java.util.properties 中的对象来配置它 XML 文件以便稍后注入值。作为稳定注入的前一步,这是我的代码:

<mule xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
 xmlns:tls="http://www.mulesoft.org/schema/mule/tls"
 xmlns:http="http://www.mulesoft.org/schema/mule/http"
 xmlns:cxf="http://www.mulesoft.org/schema/mule/cxf"
 xmlns="http://www.mulesoft.org/schema/mule/core"
 xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
 xmlns:spring="http://www.springframework.org/schema/beans" 
 xmlns:util="http://www.springframework.org/schema/util"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
 http://www.mulesoft.org/schema/mule/core 
 http://www.mulesoft.org/schema/mule/core/current/mule.xsd
 http://www.mulesoft.org/schema/mule/http 
 http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
 http://www.mulesoft.org/schema/mule/cxf 
 http://www.mulesoft.org/schema/mule/cxf/current/mule-cxf.xsd
 http://www.mulesoft.org/schema/mule/tls 
 http://www.mulesoft.org/schema/mule/tls/current/mule-tls.xsd">

 <http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="5081" doc:name="HTTP Listener Configuration"/>
 <http:request-config name="HTTP_Request_Configuration" host="${conf.prop.host}" port="${conf.prop.port}" doc:name="HTTP Request Configuration" connectionIdleTimeout="60000" responseTimeout="60000"/>

 <spring:beans>
     <spring:bean id="WrongResultException" name="WrongResultException" class="transform.WrongResultException"/>
     <spring:bean name="wsCryptoProperties" class="java.util.Properties">
         <spring:constructor-arg>
             <spring:map>
                    <spring:entry key="org.apache.ws.security.crypto.provider" value="org.apache.ws.security.components.crypto.Merlin"/>
                    <spring:entry key="org.apache.ws.security.crypto.merlin.keystore.type" value="JKS"/>
                    <spring:entry key="org.apache.ws.security.crypto.merlin.keystore.password" value="my_truststore_password"/>
                    <spring:entry key="org.apache.ws.security.crypto.merlin.file" value="my_truststore.jks"/>
                </spring:map>
            </spring:constructor-arg>
     </spring:bean>
 </spring:beans>

 <flow name="HttpsCall">
     <http:listener config-ref="https-listener-configured-in-domain-app" path="/my_path/my_service" doc:name="HTTPS"/>
     <logger message="HTTPS call" level="INFO" doc:name="Logger HTTPS"/>
     <flow-ref name="HttpCall" doc:name="HttpCall"/>
 </flow>

 <flow name="HttpCall">
     <http:listener config-ref="http-listener-configured-in-domain-app" path="/my_path/my_service" doc:name="HTTP"/>
     <cxf:proxy-service  doc:name="CXF Server" wsdlLocation="${service.protocol}://${service.host}:${service.port}${service.base_path}?${service.wsdl_file}"  payload="envelope" bindingId="${service.binding_id}" namespace="${service.namespace}" service="${service.service}" >
         <cxf:inInterceptors>
             <spring:bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
             <spring:bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
                 <spring:constructor-arg>
                     <spring:map>
                         <spring:entry key="action" value="Signature" />
                         <!-- This is how the Crypto object is configured when using a properties file
                         <spring:entry key="signaturePropFile" value="security_conf_file.properties" />-->
                         <spring:entry key="signaturePropRefId" value="wsCryptoProperties"/>
                     </spring:map>
                 </spring:constructor-arg>
             </spring:bean>
         </cxf:inInterceptors>
     </cxf:proxy-service>
     <message-properties-transformer doc:name="Message Properties">
         <add-message-property key="SOAPAction" value="#[message.inboundProperties.SOAPAction]"/>
     </message-properties-transformer>
     <cxf:proxy-client payload="envelope" doc:name="CXF Client" />
     <http:request config-ref="HTTP_Request_Configuration" path="${service.base_path}" method="POST" doc:name="HTTP" />
     <exception-strategy ref="mule-serviceCatch_Exception_Strategy" doc:name="Reference Exception Strategy"/>
 </flow>

 <catch-exception-strategy name="mule-serviceCatch_Exception_Strategy">
     <logger message="Exception: #[message]" level="INFO" doc:name="Logger"/>
     <transformer ref="WrongResultException" doc:name="Transformer Reference"/>
     <mulexml:object-to-xml-transformer doc:name="Object to XML"/>
 </catch-exception-strategy>

事实上,即使通过 java.util.Properties 配置属性,所有内容都能正确编译,但是,当调用服务时,会抛出一个错误,指出属性未正确加载:

WARN  2017-05-03 12:08:27,448 [[mule_domain_app].http-listener-configured-in-domain-app.worker.01] org.apache.ws.security.handler.WSHandler: The Crypto reference wsCryptoProperties specified by signaturePropRefId could not be loaded
WARN  2017-05-03 12:08:27,467 [[mule_domain_app].http-listener-configured-in-domain-app.worker.01] org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor: 
org.apache.ws.security.WSSecurityException: General security error (WSSecurityEngine: No crypto property file supplied to verify signature)
 at
org.apache.ws.security.message.token.X509Security.getX509Certificate(X509Security.java:100) ~[wss4j-1.6.18.jar:1.6.18]
 at 
org.apache.ws.security.message.token.SecurityTokenReference.getKeyIdentifier(SecurityTokenReference.java:491) ~[wss4j-1.6.18.jar:1.6.18] ...

等等...

有人能解释一下这个问题吗?我完全卡住了。

也许您可以在启动 mule 运行时时提供这两个参数。

./mule -M-Dorg.apache.ws.security.crypto.merlin.file=myTrustStore.jks -M-Dorg.apache.ws.security.crypto.merlin.keystore.password=myTrustStorePass

在您的 mule 配置文件中,您应该能够访问以下值:${org.apache.ws.security.crypto.merlin.file} 和 ${org.apache.ws.security.crypto.merlin.keystore.password}

不太确定这在您的用例中是否是一个有效的解决方案,但也许它可以给您新的想法...

让我们看看这是否能解决问题...我可以复制从数据库获取值并设置连接器的情况。我做的略有不同,但我想这个概念是唯一重要的事情。

在我的例子中,我从内存数据库中的 derby 获取属性,然后我使用这个道具来设置 http:listener-config

首先,我添加了一个 springBean 来保存我的属性:

<spring:beans>
        <spring:bean id="propertiesBean" name="propertiesBean" class="com.mmartinez.test.DerbyLoadProperties" />
</spring:beans>

在 DerbyLoadProperties 内部 class,是实现 InitializingBean 和 FactoryBean 所必需的。 factoryBean 将允许您 return 包含属性的 Properties 对象,在本例中来自数据库。

public class DerbyLoadProperties 实现 InitializingBean、FactoryBean {

private Properties prop = new Properties();

@Override
public void afterPropertiesSet() throws Exception {
    initializeDatabaseAndExtractProperties();
    //Inside this method I initialize the in-memory-db and also add the host and port properties from DB
    //prop.put("http.hostmario", host);
    //prop.put("http.portmario", port);
}
@Override
public Class getObjectType() {
    return Properties.class;
}

@Override
public Object getObject() throws Exception {
    return prop;
}

@Override
public boolean isSingleton() {
    return false;
}

现在我可以将我的 propertiesBean 用作 属性-placeholder

<context:property-placeholder properties-ref="propertiesBean" />

在最后一步中,我将设置我的 http:listener-config,在您的情况下是 cxf:proxy-service....

<http:listener-config port="${http.portmario}" host="${http.hostmario}" name="testListener" doc:name="HTTP Listener Configuration" />

对我来说工作正常。

已解决!

WSS4JInInterceptor 构造函数中传递的映射条目之间缺少此行:

<spring:entry key="wsCryptoProperties" value-ref="wsCryptoProperties"/>

这样做,注入 java.util.Properties 对象的属性值就像一个魅力。

希望这对以后的任何人都有帮助!