I am using spring security with filters to authenticate the users. When several users access the same service in a multi-threaded environment, the principal has changed and going for re-authentication. The password is incorrect for the user and failed to authenticate.
How can I use the pre-authentication in a multi-thread environment?
Authentication using the filter.
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy" >
<sec:filter-chain-map request-matcher="ant" >
<sec:filter-chain pattern="/**" filters="requestContextFilter,securityContextFilter,exceptionTranslationFilter,userRoleProcessingFilter" />
</sec:filter-chain-map>
</bean>
<bean id="requestContextFilter" class="org.springframework.web.filter.RequestContextFilter"/>
<bean id="securityContextFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
<constructor-arg>
<bean class="org.springframework.security.web.context.HttpSessionSecurityContextRepository"></bean>
</constructor-arg>
<property name="forceEagerSessionCreation" value="false"/>
</bean>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter" >
<constructor-arg>
<bean class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
</constructor-arg>
</bean>
<bean id="userRoleProcessingFilter"
class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
<property name="principalRequestHeader" value="CUSTOM_USER" />
<property name="credentialsRequestHeader" value="CUSTOM_CRED" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="continueFilterChainOnUnsuccessfulAuthentication" value="false" />
<property name="exceptionIfHeaderMissing" value="false"></property>
<property name="checkForPrincipalChanges" value="true"></property>
</bean>
<bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager" >
<constructor-arg>
<list>
<ref bean="authenticationProvider"/>
</list>
</constructor-arg>
</bean>
<bean id="authenticationProvider" class="com.common.authorization.spring.custom.CustomAuthenticationProvider" >
<property name="preAuthenticatedUserDetailsService">
<bean class="com.common.authorization.spring.custom.CustomUserDetailsService">
</bean>
</property>
</bean>
<bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased" >
<property name="allowIfAllAbstainDecisions" value="false"/>
<constructor-arg>
<list>
<bean class="org.springframework.security.access.vote.RoleVoter">
<property name="rolePrefix" value="" />
</bean>
</list>
</constructor-arg>
</bean>
Related
I'm trying to integrate Atomikos transaction manager into a Spring Integration program that forwards JMS from ActiveMQ to a WebMethods ESB.
The spring integration part only retrieves JMs from local ActiveMQ broker and sends them to a distant ESB broker.
When I test the nominal case, JMS is sent well and passes through the ESB and is dispatched to the subscribers then.
When I test the case where ESB sending fails, I have an issue : the JMS is never published back. I suppose it's a transaction issue because the transaction should have been rolled back when program tried to publish on ESB broker but it seems not.
Here's my spring config :
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<!-- Atomikos Transaction Manager Defintion (JTA) -->
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close" depends-on="atomikosConnectionFactorySource,connectionFactoryDestination">
<property name="transactionTimeout" value="300" />
<property name="forceShutdown" value="false" />
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
<bean id="jmsXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="${source.java.naming.provider.url}" />
<property name="userName" value="${source.username}" />
<property name="password" value="${source.passwd}" />
</bean>
<bean id="atomikosConnectionFactorySource" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="poolSize" value="1" />
<property name="uniqueResourceName" value="activemq" />
<property name="xaConnectionFactory" ref="jmsXaConnectionFactory" />
</bean>
<bean id="connectionFactorySource"
class="org.springframework.jms.connection.SingleConnectionFactory">
<property name="targetConnectionFactory" ref="jmsXaConnectionFactory" />
<property name="clientId" value="CustomerOrderForwarderID" />
<property name="reconnectOnException" value="true" />
</bean>
<!-- Destination JNDI Context -->
<bean id="jndiTemplateDestination" class="org.springframework.jndi.JndiTemplate"
lazy-init="true">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">${destination.java.naming.factory.initial}</prop>
<prop key="java.naming.provider.url">${destination.java.naming.provider.url}</prop>
<prop key="java.naming.factory.url.pkgs">${destination.java.naming.factory.url.pkgs}</prop>
</props>
</property>
</bean>
<!-- Destination Connection factory -->
<bean id="customerOrderXAConnectionFactoryDestination" class="org.springframework.jndi.JndiObjectFactoryBean"
lazy-init="true">
<property name="jndiTemplate" ref="jndiTemplateDestination" />
<property name="jndiName"
value="${destination.java.naming.factory.connection}" />
<property name="lookupOnStartup" value="false" />
<property name="proxyInterface" value="javax.jms.XAConnectionFactory" />
</bean>
<bean id="connectionFactoryDestination" class="com.atomikos.jms.AtomikosConnectionFactoryBean"
init-method="init" destroy-method="close">
<property name="poolSize" value="100" />
<property name="uniqueResourceName" value="esb" />
<property name="xaConnectionFactory" ref="customerOrderXAConnectionFactoryDestination" />
<property name="localTransactionMode" value="true" />
</bean>
<bean id="ddr" class="com.adeo.transverse.jms.forwarder.customerorder.DynamicDestinationResolver" />
<bean id="userCredentialsConnectionFactoryDestination"
class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter" lazy-init="true">
<property name="targetConnectionFactory">
<ref bean="connectionFactoryDestination" />
</property>
<property name="username" value="${destination.username}" />
<property name="password" value="${destination.passwd}" />
</bean>
Here's the integration part :
<!-- In bridge -->
<jms:message-driven-channel-adapter
id="StoreStockMotionSourceJmsAdapter" channel="bridgeChannelStoreStockMotionEnricher"
container="jmsContainerSourceStoreStockMotion" />
<!-- Channel -->
<si:channel id="bridgeChannelStoreStockMotionEnricher" />
<jms:outbound-channel-adapter id="StoreStockMotionDestinationJmsAdapter"
channel="bridgeChannelStoreStockMotionEnricher" jms-template="jmsTemplateStoreStockMotionDestination" />
<bean id="jmsTemplateStoreStockMotionDestination" class="org.springframework.jms.core.JmsTemplate">
<property name="transactionManager" ref ="transactionManager"/>
<property name="connectionFactory" ref="userCredentialsConnectionFactoryDestination" />
<property name="defaultDestinationName" value="${StoreStockMotion.destination.topic}" />
<property name="defaultDestination" ref="StoreStockMotionDestinationTopic" />
<property name="pubSubDomain" value="true"/>
</bean>
<!-- Topic JMS for published message -->
<bean id="StoreStockMotionDestinationTopic" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
<property name="jndiTemplate">
<ref bean="jndiTemplateDestination" />
</property>
<property name="jndiName">
<value>${StoreStockMotion.destination.topic}</value>
</property>
</bean>
<!-- Topic JMS for Subscribing Message -->
<bean id="jmsContainerSourceStoreStockMotion"
class="org.springframework.jms.listener.DefaultMessageListenerContainer"
lazy-init="true">
<property name="connectionFactory" ref="connectionFactorySource" />
<property name="destinationName" value="${StoreStockMotion.source.topic}" />
<property name="subscriptionDurable" value="true" />
<!-- 2 is client acknowledge -->
<property name="sessionAcknowledgeMode" value="2" />
<property name="durableSubscriptionName" value="${StoreStockMotion.source.subname}" />
<property name="sessionTransacted" value="false" />
<property name="pubSubDomain" value="true"/>
</bean>
Source and Destination are both encapsulated in XA connection factories and transactionManager handles the two transactions. Any idea what's missing ?
The first request made to the messageSender via a webservicetemplate using credential is failing with 401 unauthorized, but second time it is all okay and works well.
Configuration:
<property name="messageSender">
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="connectionTimeout" value="900000" />
<property name="readTimeout" value="0" />
<property name="credentials">
<bean class="org.apache.http.auth.UsernamePasswordCredentials">
<constructor-arg value="${userName}:${Password}" />
</bean>
</property>
From so far, what i have googled through I get to know that I will have to do a preemptive authentication to avoid 401 unauthorized using [org.apache.http.client.HttpClient]. I want a spring xml configuration to allow this so that I can configure preemptive authentication.
Also, is the behaviour as expected.
What I have tried so far.
class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="connectionTimeout" value="900000" />
<property name="readTimeout" value="0" />
<property name="httpClient" ref="httpClient" />
<property name="credentials" ref="credentials"/>
</bean>
</property>
<bean id="httpClient" class="org.apache.http.client.HttpClient">
<!-- Not Sure what configuration to add here -->
</bean>
<bean id="credentials" class="org.apache.http.auth.UsernamePasswordCredentials">
<constructor-arg value="${userName}:${password}" />
</bean>
Creating the http client with a credentials provider, which need UsernamePasswordCredentials and AuthScope. AuthScope is created with default values and UsernamePasswordCredentials is created with username, password. BasicCredentialsProvider does not take provider and credentials in constructor or setter method. It has to set by invoking setCredentials() method.
<bean class="org.springframework.ws.transport.http.HttpComponentsMessageSender">
<property name="connectionTimeout" value="900000"/>
<property name="readTimeout" value="0"/>
<property name="httpClient" ref="httpClient"/>
</bean>
<bean id="credentialProvider" class="org.apache.http.impl.client.BasicCredentialsProvider" />
<bean id="methodInvoke" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject"><ref local="credentialProvider" /> </property>
<property name="targetMethod" value="setCredentials"> </property>
<property name="arguments" >
<list>
<ref local="authScope" />
<ref local="credentials" />
</list>
</property>
</bean>
<bean id="authScope" class="org.apache.http.auth.AuthScope">
<constructor-arg name="host"><null /></constructor-arg>
<constructor-arg><value>-1</value> </constructor-arg>
<constructor-arg><null /></constructor-arg>
<constructor-arg><null /></constructor-arg>
</bean>
<bean id="credentials" class="org.apache.http.auth.UsernamePasswordCredentials">
<constructor-arg name="userName"><value>xxx</value></constructor-arg>
<constructor-arg name="password"><value>xxx</value></constructor-arg>
</bean>
<bean id="httpClient" class="org.apache.http.impl.client.DefaultHttpClient">
<property name="credentialsProvider" ref="credentialProvider"/>
</bean>
The configuration which I had to add to the Webservicetemplate are shown below:
<!-- Custom Interceptor Implementation to WebServiceTemplate -->
<property name="interceptors">
<list>
<bean class="com.utils.AddHttpHeaderInterceptor" >
</bean>
</list>
</property>
And implement the AddHttpHeaderInterceptor class which implements ClientInterceptor as below:
HttpPost postMethod = connection.getHttpPost();
postMethod.addHeader("Authorization", "Basic " + base64Creds);
return true;
And note: base64Creds is nothing but base64.encode(username:pwd)
Currently we are using jasig CAS server for SSO solution. We have two web application that is using same CAS server. We are using spring security for configuring CAS client. Sample code is like :
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant" >
<sec:filter-chain pattern="/j_spring_security_logout(.jsp)*" filters="appLogoutFilter,exceptionTranslationFilter,filterSecurityInterceptor"/>
<sec:filter-chain pattern="/**"
filters="securityContextPersistenceFilter,requestSingleLogoutFilter,appLogoutFilter,casAuthenticationFilter,requestCacheFilter,contextAwareFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
</sec:filter-chain-map>
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="casAuthenticationProvider" />
</sec:authentication-manager>
<bean id="casAuthenticationProvider" class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService" ref="userDetailsServiceWrapper"/>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator" ref="ticketValidator"/>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>
<bean id="userDetailsServiceWrapper" class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<property name="userDetailsService" ref="lormsSecurityUserDetailsService"/>
</bean>
<bean id="exceptionTranslationFilter" class="org.springframework.security.web.access.ExceptionTranslationFilter">
<constructor-arg ref="casEntryPoint"/>
<property name="accessDeniedHandler" ref="accessDeniedHandler"/>
</bean>
<bean id="appLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="/j_spring_cas_security_logout"/>
<constructor-arg>
<list>
<ref bean="lormsLogOutHandler"/>
</list>
</constructor-arg>
<property name="logoutRequestMatcher">
<bean class="org.springframework.security.web.util.matcher.RegexRequestMatcher">
<constructor-arg name="pattern" value="/j_spring_security_logout(.jsp)*" />
<constructor-arg name="httpMethod">
<null/>
</constructor-arg>
</bean>
</property>
</bean>
<!-- This filter redirects to the CAS Server to signal Single Logout should be performed ?service=${singleSignOn.cas.app.url}/LORMS -->
<bean id="requestSingleLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="${singleSignOn.cas.server.url}/logout?service=${singleSignOn.cas.app.url}/LORMS"/>
<constructor-arg>
<bean class= "org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<property name="logoutRequestMatcher">
<bean class="org.springframework.security.web.util.matcher.RegexRequestMatcher">
<constructor-arg name="pattern" value="/j_spring_cas_security_logout(.jsp)*" />
<constructor-arg name="httpMethod">
<null/>
</constructor-arg>
</bean>
</property>
</bean>
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator" id="ticketValidator">
<constructor-arg index="0" value="${singleSignOn.cas.server.url}" />
</bean>
<bean id="proxyGrantingTicketStorage" class="org.jasig.cas.client.proxy.ProxyGrantingTicketStorageImpl" />
<bean id="casAuthenticationFilter" class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationSuccessHandler" ref="authenticationSuccessHandler"/>
</bean>
<bean id="casEntryPoint" class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="${singleSignOn.cas.server.url}/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>
<bean id="serviceProperties" class="org.springframework.security.cas.ServiceProperties">
<property name="service" value="${singleSignOn.cas.app.url}/LORMS/j_spring_cas_security_check"/>
<property name="sendRenew" value="false"/>
</bean>
Now I have existing form based login UI. I want to use same instead of using jasig web login screen. I found this link "Using CAS from external link or custom external form" using which I can use my login UI. Can anybody help me to integrate same with spring security in my application ?
After you integrate your application.you can change and edit casviewpage.jsp.You can change all UI.You use default casview.jsp and edit it.Why dont want to edit casview.jsp?
When using pre-configured service provider metadata, in spring security, should there be 2 beans definitions for extended metadata delegate ? one for IDP metadata, and one for SP metadata ?
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">classpath:security/localhost_sp.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="local" value="true"/>
<property name="alias" value="default"/>
<property name="securityProfile" value="metaiop"/>
<property name="sslSecurityProfile" value="pkix"/>
<property name="signingKey" value="apollo"/>
<property name="encryptionKey" value="apollo"/>
<property name="requireArtifactResolveSigned" value="false"/>
<property name="requireLogoutRequestSigned" value="false"/>
<property name="requireLogoutResponseSigned" value="false"/>
<property name="idpDiscoveryEnabled" value="true"/>
<property name="idpDiscoveryURL"
value="https://www.server.com:8080/context/saml/discovery/alias/default"/>
<property name="idpDiscoveryResponseURL"
value="https://www.server.com:8080/context/saml/login/alias/default?disco=true"/>
</bean>
</constructor-arg>
</bean>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">classpath:security/idp.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata"/>
</constructor-arg>
</bean>
Found the answer to my question....positing it here in case someone else looking for the same.
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.HTTPMetadataProvider">
<constructor-arg>
<value type="java.lang.String">http://idp.ssocircle.com/idp-meta.xml</value>
</constructor-arg>
<constructor-arg>
<!-- Timeout for metadata loading in ms -->
<value type="int">5000</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata"/>
</constructor-arg>
<property name="metadataTrustCheck" value="false"/>
</bean>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">file:///C:/SP_Metadata.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="local" value="true"/>
<property name="alias" value="defaultAlias"/>
<property name="securityProfile" value="metaiop"/>
<property name="sslSecurityProfile" value="pkix"/>
<property name="signingKey" value="apollo"/>
<property name="encryptionKey" value="apollo"/>
<property name="requireArtifactResolveSigned" value="true"/>
<property name="requireLogoutRequestSigned" value="true"/>
<property name="requireLogoutResponseSigned" value="false"/>
<property name="idpDiscoveryEnabled" value="true"/>
<property name="idpDiscoveryURL" value="https://localhost/mywebapp-SNAPSHOT/saml/discovery/alias/defaultAlias"/>
<property name="idpDiscoveryResponseURL" value="https://localhost/mywebapp-SNAPSHOT/saml/login/alias/defaultAlias?disco=true"/>
</bean>
</constructor-arg>
</bean>
</list>
</constructor-arg>
<!-- my SP_metadata had this as the entity id -->
<property name="hostedSPName" value="urn:test:myapp:auth"/>
<!-- my idp metadata points to the sso circle idp -->
<property name="defaultIDP" value="http://idp.ssocircle.com"/>
</bean>
For some reason the ReloadablePropertiesFactoryBean doens't seem to do what I expect. When I change a property in the test.properties file I get a log message saying:
9979 [timer] INFO com.krest.core.properties.ReloadablePropertiesFactoryBean - Reloading Properties...
But for some reason nothing happens. The old property value is still set on my test bean. Does anybody know why this is? I use Spring 3 and my configuration looks like this:
<bean id="configproperties"
class="com.krest.core.properties.ReloadablePropertiesFactoryBean">
<property name="location"
value="classpath:test.properties" />
</bean>
<bean id="propertyConfigurer"
class="com.krest.core.properties.ReloadingPropertyPlaceholderConfigurer">
<property name="properties" ref="configproperties" />
<property name="reloadingPlaceholderPrefix" value="rel{" />
<property name="reloadingPlaceholderSuffix" value="}" />
</bean>
<bean id="mybean" class="nl.mycompany.TestBean">
<property name="message" value="rel{timer-delay}" />
</bean>
<!-- regularly reload property files. -->
<bean id="timer" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<bean id="reloadProperties"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="period" value="1000" />
<property name="runnable">
<bean class="com.krest.core.properties.ReloadConfiguration">
<property name="reconfigurableBeans">
<list>
<ref bean="configproperties" />
</list>
</property>
</bean>
</property>
</bean>
</property>
</bean>