Spring WebServiceTemplate Interceptor for adding security header - spring

I am trying to add a SOAP:Header with wss4j authentication for my outbound SOAP service.
Below is my WebServiceTemplate and interceptor configuration
<bean id="securityHeader"
class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
<property name="securementActions" value="UsernameToken" />
<property name="securementUsername" value="uname" />
<property name="securementPassword" value="password#123" />
<property name="securementPasswordType" value="PasswordText" />
<property name="securementUsernameTokenElements" value="Nonce Created" />
</bean>`
<bean id="webService" class="org.springframework.ws.client.core.WebServiceTemplate">
<constructor-arg ref="messageFactory" />
<property name="messageSender">
<bean
class="org.springframework.ws.transport.http.CommonsHttpMessageSender">
<!-- <property name="credentials" ref="credentials" /> -->
</bean>
</property>
<property name="interceptors">
<list>
<ref bean="securityHeader" />
</list>
</property>
<property name="defaultUri"
value="https://test.test.com/ws/service/test" />
<property name="marshaller" ref="fmarshaller" />
<property name="unmarshaller" ref="forwardunmarshaller" />
</bean>
But when the outbound call happens, its not adding the SOAP security header.webService.marshalSendAndReceive("http://localhost:8088/mockBinding",request);

Below changes did the trick for me.
Changing the SOAP version to 1.1
Defining the bean declaration inside interceptor instead of referencing it.
Use a web service message callback.

Related

WebLogic 10.3.6 throws JMSClientExceptions:055142 when configured with lookupOnStartup false

I have simple Java Spring application which looks up JMS objects using JNDI and publishes a message to a JMS Topic. JNDI and JMS configured on WebLogic 10.3.6. All this works fine as long as the WebLogic server is up and running.
I need to get the application to start up even when the WebLogic server is down. I have configured the JNDI objects with "lookupOnStartup" as "false".
Below is my Spring configuration.
<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${jndi.initialFactory}</prop>
<prop key="java.naming.provider.url">${jndi.providerurl}</prop>
</props>
</property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${jms.connectionFactory}</value>
</property>
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.ConnectionFactory" />
</bean>
<bean id="myTopic" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>${jms.mytopic}</value>
</property>
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.Destination" />
</bean>
<bean id="jmsDestinationResolver"
class="org.springframework.jms.support.destination.JndiDestinationResolver">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="cache" value="true" />
</bean>
<bean id="myTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestination" ref="myTopic" />
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />
</bean>
At runtime I get the following exception:
Exception in thread "main" org.springframework.jms.InvalidDestinationException: [JMSClientExceptions:055142]Foreign destination, jmsserver-module!my-topic; nested exception is weblogic.jms.common.InvalidDestinationException: [JMSClientExceptions:055142]Foreign destination, jmsserver-module!my-topic
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:285)
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:497)
at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:569)
...
Caused by: weblogic.jms.common.InvalidDestinationException: [JMSClientExceptions:055142]Foreign destination, jmsserver-module!my-topic
at weblogic.jms.common.Destination.checkDestinationType(Destination.java:105)
at weblogic.jms.client.JMSSession.setupJMSProducer(JMSSession.java:2830)
at weblogic.jms.client.JMSSession.createProducer(JMSSession.java:2858)
at weblogic.jms.client.JMSSession.createProducer(JMSSession.java:2822)
at weblogic.jms.client.WLSessionImpl.createProducer(WLSessionImpl.java:827)
at org.springframework.jms.core.JmsTemplate.doCreateProducer(JmsTemplate.java:1143)
at org.springframework.jms.core.JmsTemplate.createProducer(JmsTemplate.java:1124)
at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:601)
at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:572)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:494)
... 3 more
Any help is much appreciated. Thank you!
In Destination.java:
if(!(destination instanceof DestinationImpl))
throw new InvalidDestinationException
The proxied connectionFactory is not able to resolve the the destination type. I was able to resolve this issue by providing only the destination name to the JmsTemplate and using a JNDI destinationResolver to resolve the destination type on demand. So the modified Spring configuration looks like:
<bean id="myTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="defaultDestinationName">
<value>${jms.mytopic}</value>
</property>
<property name="destinationResolver" ref="jmsDestinationResolver" />
<property name="connectionFactory" ref="connectionFactory" />
<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE" />
<property name="sessionTransacted" value="false" />

Release the attribute from CAS to Spring security

I am using a Spring security 3.X on the client side and CAS 4.0 on the server.
When i am doing CAS+Spring security integration, I am able to reach the level of ticket validation success and able to get the proper roles at the client side.
But I have added the following lines in my casServiceValidationSuccess.jsp to iterate and send the attributes in my response as my attributes are not released properly:
<cas:attributes>
<cas:user>${fn:escapeXml(assertion.primaryAuthentication.principal.id)}</cas:user>
<c:forEach var="attr" items="${assertion.chainedAuthentications[fn:length(assertion.chainedAuthentications)-1].principal.attributes}">
<cas:${fn:escapeXml(attr.key)}>${fn:escapeXml(attr.value)}</cas:${fn:escapeXml(attr.key)}>
</c:forEach>
</cas:attributes>
So wants to know is there any other alternative changes to do in deployerConfigContext.xml in the CAS server side to release particular attribute-"authorities" in my case and to get the same in SPRING client side.
Find the snippets of existing deployerConfigContext.xml where trying to release "authorities" attributes:
<bean id="authenticationManager" class="org.jasig.cas.authentication.PolicyBasedAuthenticationManager">
<constructor-arg>
<map>
<entry key-ref="proxyAuthenticationHandler" value-ref="proxyPrincipalResolver" />
<entry key-ref="primaryAuthenticationHandler" value-ref="primaryPrincipalResolver" />
</map>
</constructor-arg>
<bean id="primaryAuthenticationHandler" class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">
<property name="dataSource" ref="dataSource" />
<property name="sql" value="SELECT EMAIL FROM USER_DATA WHERE UserID = ?" />
</bean>
<bean id="primaryPrincipalResolver"
class="org.jasig.cas.authentication.principal.PersonDirectoryPrincipalResolver" >
<property name="attributeRepository" ref="attributeRepository" />
</bean>
<bean id="attributeRepository"
class="org.jasig.services.persondir.support.jdbc.SingleRowJdbcPersonAttributeDao">
<constructor-arg index="0" ref="dataSource" />
<constructor-arg index="1" value="SELECT UserID, UserROLES FROM USER_DATA WHERE {0}" />
<property name="queryAttributeMapping">
<map>
<entry key="username" value="UserID" />
</map>
</property>
<property name="resultAttributeMapping">
<map>
<entry key="UserID" value="username" />
<entry key="UserROLES" value="UserROLES" />
</map>
</property>
</bean>
<bean id="serviceRegistryDao" class="org.jasig.cas.services.InMemoryServiceRegistryDaoImpl">
<property name="registeredServices">
<list>
<bean class="org.jasig.cas.services.RegisteredServiceImpl">
<property name="id" value="0"></property>
<property name="name" value="HTTP"></property>
<property name="description" value="Only Allows HTTP Urls"></property>
<property name="serviceId" value="http://**" />
<property name="usernameAttribute" value="username" />
<property name="ignoreAttributes" value="false" />
<property name="allowedAttributes">
<list>
<value>UserROLES</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
Also find the security-context.xml at the spring client side:
<security:http use-expressions="true" entry-point-ref="casAuthenticationEntryPoint"
auto-config="true">
<security:custom-filter position="CAS_FILTER"
ref="casAuthenticationFilter"></security:custom-filter>
<security:intercept-url pattern="/home" access="hasRole('ROLE_TEST')"></security:intercept-url>
<security:intercept-url pattern="/**" access="hasRole('ROLE_ANONYMOUS')"></security:intercept-url>
</security:http>
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider
ref="casAuthenticationProvider"></security:authentication-provider>
</security:authentication-manager>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="http://localhost:7080/test/j_spring_cas_security_check"></property>
<property name="sendRenew" value="false"></property>
</bean>
<bean id="casAuthenticationFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"></property>
<property name="authenticationFailureHandler">
<bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="http://localhost:8090/cas-server-webapp-4.0.0/login"/>
</bean>
</property>
<property name="authenticationSuccessHandler">
<bean class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/home.jsp"/>
</bean>
</property>
</bean>
<bean id="casAuthenticationEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl"
value="http://localhost:8090/cas-server-webapp-4.0.0/login"></property>
<property name="serviceProperties" ref="serviceProperties"></property>
</bean>
<!-- Handles the CAS ticket processing. -->
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<!-- <property name="userDetailsService" ref="userService"></property> -->
<property name="authenticationUserDetailsService" ref="authenticationUserDetailsService" />
<property name="serviceProperties" ref="serviceProperties"></property>
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0"
value="http://localhost:8090/cas-server-webapp-4.0.0">
</constructor-arg>
</bean>
</property>
<property name="key" value="cas"></property>
</bean>
<bean id="authenticationUserDetailsService"
class="org.springframework.security.cas.userdetails.GrantedAuthorityFromAssertionAttributesUserDetailsService">
<constructor-arg>
<list>
<value>UserROLES</value>
</list>
</constructor-arg>
</bean>
</beans>
Disclaimer: I'm the Chairman of CAS and founder of CAS in the cloud (https://www.casinthecloud.com).
Is your attribute person DAO referenced by your authentication handler? Does it work without Spring security doing a manual service ticket validation?

Spring MDP not Consuming Message

I am implementing Spring MDP + JMSTemplate to send and receive the message. The message send mechanism is working fine, however the MDP is not getting invoked. I tried testing the via plain receiver, and was able to retrieve the message, but not via MDP. What could be the problem? I can see the messages getting accumulated in the request queue, but somehow the MDP is not getting trigger. Am I missing anything here in configurations or something else needs to be taken care of?
Here's the Spring Config. The Java class to send and received are pretty much standard ones.
<bean id="cookieRequestListener" class="com.text.jms.mq.mdp.RequestQueueMDP">
<property name="logger" ref="mqLogger" />
<property name="scoringEngine" ref="scoringEngine" />
<property name="mqSender" ref="jmsMQSender" />
</bean>
<bean id="CookieRequestContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="cachedConnectionFactory" />
<property name="destination" ref="jmsRequestQueue" />
<property name="messageListener" ref="cookieRequestListener" />
</bean>
<bean id="jmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:/jms/queueCF</value>
</property>
</bean>
<!-- A cached connection to wrap the Queue connection -->
<bean id="cachedConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
<property name="targetConnectionFactory" ref="jmsConnectionFactory"/>
<property name="sessionCacheSize" value="10" />
</bean>
<!-- jms Request Queue Configuration -->
<bean id="jmsRequestQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:/jms/cookieReqQ</value>
</property>
</bean>
<!-- jms Response Queue Configuration -->
<bean id="jmsResponseQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jndiTemplate" />
</property>
<property name="jndiName">
<value>java:/jms/cookieResQ</value>
</property>
</bean>
<bean id="jmsJMSTemplate" class="org.springframework.jms.core.JmsTemplate" >
<property name="connectionFactory" ref="cachedConnectionFactory" />
</bean>
<!-- jms MQ Utility -->
<bean id="jmsMQSender" class="com.text.jms.util.MQSender">
<property name="jmsTemplate">
<ref bean="jmsJMSTemplate"></ref>
</property>
<property name="defaultDestination">
<ref bean="jmsRequestQueue" />
</property>
<property name="logger" ref="mqLogger" />
</bean>

JNDI access with Tomcat 7 and embedded HornetQ

I set up a new project with Tomcat 7.0 and an embedded HornetQ JMS server.
I used these 2 tutorials to help me:
http://www.javacodegeeks.com/2010/06/spring-3-hornetq-21-integration.html
http://wash-inside-out.blogspot.com/2010/08/hornetq-jms-integration-with-tomcat.html
But as it is mentioned in the tutos, the Tomcat JNDI repository is readonly (cannot find a way to write) and I configured a "separated" JNDI used by HornetQ, the messaging works, but Tomcat cannot access it.
Normally, in my other projects using Tomcat, I defined the datasource as a global resource in the server.xml and I map it in the context.xml. doing this, the definition of the datasource (jdbc url, credentials, etc...) are outside the application and can be managed by environment (dev, test, prod, ...) but I cannot find a way to do it with the other JNDI.
Currently, the datasource is defined in my application with an external property file for the parameters but I am not really satisfied with this solution.
Here is my Spring configuration:
<!-- enable autowire -->
<context:annotation-config />
<!-- enable transaction demarcation with annotations -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
<property name="driverClassName" value="com.informix.jdbc.IfxDriver" />
<property name="url" value="${URL}" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
<property name="maxActive" value="50" />
<property name="maxIdle" value="10" />
<property name="maxWait" value="1000" />
<property name="removeAbandoned" value="true" />
<property name="removeAbandonedTimeout" value="300" />
<property name="logAbandoned" value="true" />
</bean>
<!-- HornetQ config -->
<bean name="namingServerImpl" class="org.jnp.server.NamingBeanImpl" init-method= "start" destroy-method="stop" >
<!-- configure HornetQ JNDI server not to use an existing JNDI service if available -->
<property name="useGlobalService" value="false" />
</bean>
<bean name="namingServer" class="org.jnp.server.Main" init-method="start" destroy-method="stop">
<property name="namingInfo" ref="namingServerImpl" />
<property name="port" value="1099" />
<property name="bindAddress" value="localhost" />
<property name="rmiPort" value="1098" />
<property name="rmiBindAddress" value="localhost" />
</bean>
<bean name="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer" />
<bean name="fileConfiguration" class="org.hornetq.core.config.impl.FileConfiguration"
init-method="start" destroy-method="stop" />
<bean name="hornetQSecurityManagerImpl" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl" />
<!-- The core server -->
<bean name="hornetQServerImpl" class="org.hornetq.core.server.impl.HornetQServerImpl">
<constructor-arg index="0" ref="fileConfiguration" />
<constructor-arg index="1" ref="mbeanServer" />
<constructor-arg index="2" ref="hornetQSecurityManagerImpl" />
</bean>
<!-- The JMS server -->
<bean name="jmsServerManagerImpl" class="org.hornetq.jms.server.impl.JMSServerManagerImpl"
init-method="start" destroy-method="stop" depends-on="namingServer">
<constructor-arg ref="hornetQServerImpl" />
</bean>
<!-- to use HornetQ messaging service through Spring we can either create a connection factory, or lookup one from JNDI -->
<bean name="connectionFactory" class="org.hornetq.jms.client.HornetQConnectionFactory">
<constructor-arg index="0" type="boolean" value="false"/>
<constructor-arg index="1">
<bean class="org.hornetq.api.core.TransportConfiguration">
<constructor-arg index="0" type="java.lang.String" value="org.hornetq.integration.transports.netty.NettyConnectorFactory" />
<constructor-arg index="1">
<map key-type="java.lang.String" value-type="java.lang.Object">
<entry key="port" value="5445"></entry>
</map>
</constructor-arg>
</bean>
</constructor-arg>
</bean>
<bean id="notificationsQueue" class="org.springframework.jndi.JndiObjectFactoryBean" depends-on="jmsServerManagerImpl">
<property name="jndiName">
<value>/queue/Notifications</value>
</property>
</bean>
<bean id="inVMConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" depends-on="jmsServerManagerImpl">
<property name="jndiName">
<value>/ConnectionFactory</value>
</property>
</bean>
How can I managed it in a better way, I mean, define the datasource on the server side as usual? Is there a configuration to tell Tomcat to use the external JNDI I defined or create a read/write repo?

Calling spring bean from alfresco activiti process

Within alfresco activiti, could I call a spring bean using the servicetask like :
<serviceTask id="assignApplicationId" name="Assign Application Id"
activiti:expression="${sequenceUtil.getOutboundId(task.id)}"
activiti:resultVariable="OutboundWF_ApplicationNumber"/>
however, in my custom context I declared the sequenceUtil as the following:
<bean id="sequenceUtil" name="sequenceUtil" class="com.tts.mersal.presentation.bean.dialog.util.SequenceUtil">
<property name="searchService">
<ref bean="searchService" />
</property>
<property name="nodeService">
<ref bean="nodeService" />
</property>
<property name="workflowService">
<ref bean="WorkflowService" />
</property>
</bean>
Actually I got the following exception
org.activiti.engine.impl.javax.el.PropertyNotFoundException: Cannot resolve identifier 'sequenceUtil'
at org.activiti.engine.impl.juel.AstIdentifier.eval(AstIdentifier.java:83)
at org.activiti.engine.impl.juel.AstMethod.invoke(AstMethod.java:79)
at org.activiti.engine.impl.juel.AstMethod.eval(AstMethod.java:75)
at org.activiti.engine.impl.juel.AstEval.eval(AstEval.java:50)
at org.activiti.engine.impl.juel.AstNode.getValue(AstNode.java:26)
at org.activiti.engine.impl.juel.TreeValueExpression.getValue(TreeValueExpression.java:114)
at org.activiti.engine.impl.el.JuelExpression.getValue(JuelExpression.java:46)
I got it :)
I have to override the activitiProcessEngineConfiguration bean to include my custom bean within beans property
<!-- -->
<!-- Activiti Process Engine -->
<!-- -->
<bean id="activitiProcessEngineConfiguration"
class="org.alfresco.repo.workflow.activiti.AlfrescoProcessEngineConfiguration">
<property name="dataSource" ref="wrappedDataSource" />
<property name="transactionManager" ref="transactionManager" />
<property name="databaseSchemaUpdate" value="${db.schema.update}" />
<property name="history" value="full" />
<property name="jobExecutorActivate" value="true" />
<!-- Limit the visible beans in expressions -->
<property name="beans">
<map>
<entry key="services" value-ref="ServiceRegistry" />
<entry key="sequenceUtil" value-ref="sequenceUtil" />
</map>
</property>
<property name="customTypes">
<list>
<ref bean="activitiScriptNodeType" />
<ref bean="activitiScriptNodeListType" />
</list>
</property>
<property name="customPreBPMNParseListeners">
<list>
<ref bean="activitiParseListener" />
</list>
</property>
</bean>
There is a much better way to map bean names to el epressions. At least for alfresco 5.2.
Originally activitiProcessEngineConfiguration defined like that:
<bean id="activitiProcessEngineConfiguration" class="org.alfresco.repo.workflow.activiti.AlfrescoProcessEngineConfiguration">
<!-- Limit the visible beans in expressions -->
<property name="beans" ref="activitiBeanRegistry" />
</bean>
Where activitiBeanRegistry defined like that:
<util:map id="activitiBeanRegistry" map-class="java.util.HashMap">
<entry key="services" value-ref="ServiceRegistry" />
</util:map>
So you can easy add your beans with names without touching original activitiProcessEngineConfiguration. Like that:
<bean id="my.activitiBeanRegistry" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" depends-on="activitiBeanRegistry">
<property name="targetObject">
<ref bean="activitiBeanRegistry" />
</property>
<property name="targetMethod" value="put" />
<property name="arguments">
<list>
<value>sequenceUtil</value>
<ref bean="sequenceUtil" />
</list>
</property>
Open for extension closed for modification :)
Full source can be found here
See also activiti-context.xml

Resources