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

时间:2017-03-22 09:55:30

标签: spring mule ws-security properties-file wss4j

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

我项目中的相关数据现在看起来像这样:

流程中的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参数,并将它们设置在DataBase中以便注入。

我徒劳无功(像util这样的标签:属性正在抛出一个'前缀'util“for element”util:properties“is not bound”error)尝试了类似于此处所示的方法: 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}

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

感谢。

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

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

<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] ...

等等......

有人可以对这个问题有所了解吗?我完全卡住了。

3 个答案:

答案 0 :(得分:0)

也许你可以在启动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}

不确定这是否是您用例中的有效解决方案,但也许它可以为您提供新的想法......

答案 1 :(得分:0)

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

在我的情况下,我从内存数据库中的derby获取属性,然后我使用这个props来设置http:listener-config

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

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

在DerbyLoadProperties类中,必须实现InitializingBean和FactoryBean。 factoryBean将允许您返回包含属性的Properties对象,在这种情况下来自数据库。

公共类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用作属性占位符

<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" />

对我来说工作正常。

答案 2 :(得分:0)

解决!

在WSS4JInInterceptor构造函数中传递的地图条目之间缺少此行:

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

执行此操作时,注入java.util.Properties对象的props的值将作为魅力。

希望这有助于将来的任何人!