Spring Session changed the cookie value causing HTTP 302 on succeeding requests - spring

Migrating from servlet container HTTP session to spring session has caused HTTP 302 after successful login. I've got an HTTP 200 on first request after login, but succeeding requests seem redirected to login page again. Cannot debug on succeeding requests as it seems not able to reach through the servlet where I put some breakpoint.
Right now, we are using spring session 1.3.5 version. And have noticed that in spring's SessionRepositoryFilter, it replaced the original request cookies (e.g. servlet container) to the value from spring session. I am not sure if this is the root cause of the issue. If it is, can someone suggest how to resolve it? Or is it related to some sort of missing configuration?
Here's the current setup based on the guide from spring session: here
Spring session XML configuration:
<context:annotation-config/>
<bean class="org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration"/>
<bean id="hazelcastInstance" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="com.xxx.xxx.xxx.xxx.CustomHazelcastProvider.getInstance"/>
</bean>
<bean class="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookieName" value="JSESSIONID"/>
<property name="cookiePath" value="/"/>
<property name="domainNamePattern" value="^.+?\.(\w+\.[a-z]+)$"/>
</bean>
Reference of spring XML configuration in web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:application-context.xml</param-value>
</context-param>
Registration of spring session repository filter in web.xml. As describe in the guide, I placed it as the first entry of the filter chain.
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/rs/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
I have been working on it for days now and don't know yet how to fix it. Will appreciate any help or suggestion that you can advise.
Thank you in advance.

I resolved the issue using spring session HeaderHttpSessionStrategy.
Steps I've made:
In my spring session XML configuration, I removed the entry related to cookie serializer to change the cookie name.
<bean class="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookieName" value="JSESSIONID"/>
<property name="cookiePath" value="/"/>
<property name="domainNamePattern" value="^.+?\.(\w+\.[a-z]+)$"/>
</bean>
By default, spring session uses CookieHttpSessionStrategy. Added below entry in spring session XML configuration.
<bean id="httpSessionStrategy" class="org.springframework.session.web.http.HeaderHttpSessionStrategy"/>
Then on every request, I am passing x-auth-token in the http request header.
After the said change, the application works as expected. Able to login without an issue.
Hope this solution will help others who have encountered the same issue.

Related

Does Spring Session require the use of Spring Security?

Does spring session internally require the use of spring security?
Right now, we have an existing application which uses HTTP session from servlet container (e.g. WebLogic). Due to some issues on session replication and for future plans to use another servlet container, we decided to look for existing framework that would make the HTTP session container independent.
The team decided to look at Spring Session in combination with Hazelcast as described in official documentation. We use spring session version 1.3.5.RELEASE.
For hazelcast configuration, we use this session configuration.
<context:annotation-config/>
<bean class="org.springframework.session.hazelcast.config.annotation.web.http.HazelcastHttpSessionConfiguration"/>
<bean id="hazelcastInstance" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="staticMethod" value="xxx.xxx.xxx.cache.CustomHazelcastProvider.getInstance"/>
</bean>
<bean class="org.springframework.session.web.http.SessionEventHttpSessionListenerAdapter">
<constructor-arg>
<list>
<bean class="xxx.xxx.xxx.util.CustomHttpSessionListener"/>
</list>
</constructor-arg>
</bean>
<bean class="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookieName" value="JSESSIONID"/>
<property name="cookiePath" value="/"/>
<property name="domainNamePattern" value="^.+?\.(\w+\.[a-z]+)$"/>
</bean>
In web.xml, we put this filter chain.
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>CustomServletRequestFilter</filter-name>
<filter-class>xxx.xxx.xxx.servlet.filter.CustomServletRequestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CustomServletRequestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
And added spring configuration below in web.xml
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:application-context.xml</param-value>
</context-param>
In the same web.xml, we use form-based authentication.
<login-config>
<auth-method>FORM</auth-method>
<realm-name>myrealm</realm-name>
<form-login-config>
<form-login-page>/login.html</form-login-page>
<form-error-page>/loginerror.html</form-error-page>
</form-login-config>
</login-config>
In addition, we are using the default cookie based HTTP strategy.
After deploying the said changes in weblogic, we are able to get a successful login. Able to check the session ID coming from spring session. However, the next hop or succeeding REST calls, it always returns HTTP 302. It gets redirected to login page.
Does spring session require the use of spring security? Is there some configuration that we need to add to resolve this issue?
Will appreciate any help or suggestion to resolve this issue.
Thank you.

the attributes 'j_username' and 'j_password' were shown as a plain text under Form Data in the request header

I am facing one of a security issue that Chrome dev tools were showing these attributes 'j_username' and 'j_password' as a plain text under Form Data in the request header.
It is an old application, in which we are using acegi-security 0.8.2 with Spring framework.
Workaround in our project: 1. in web.xml, we have mentioned the filter ChannelProcessingFilter as a separate filter,
<filter>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>net.sf.acegisecurity.util.FilterChainProxy
</param-value>
</init-param>
</filter>
<filter>
<filter-name>Acegi Channel Processing Filter</filter-name>
<filter-class>net.sf.acegisecurity.util.FilterToBeanProxy</filter-class>
<init-param>
<param-name>targetClass</param-name>
<param-value>
net.sf.acegisecurity.securechannel.ChannelProcessingFilter</param-value>
</init-param>
</filter>
2..In applicationContext.xml, we have defined the ChannelProcessingFilter,
<bean id="channelProcessingFilter" class="net.sf.acegisecurity.securechannel.ChannelProcessingFilter">
<property name="channelDecisionManager"><ref bean="channelDecisionManager"/></property>
<property name="filterInvocationDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/login.htm*=REQUIRES_SECURE_CHANNEL
/j_acegi_security_check*=REQUIRES_SECURE_CHANNEL
/admin/**=REQUIRES_SECURE_CHANNEL
/**=REQUIRES_INSECURE_CHANNEL
</value>
</property>
</bean>
<bean id="channelDecisionManager" class="net.sf.acegisecurity.securechannel.ChannelDecisionManagerImpl">
<property name="channelProcessors">
<list>
<ref bean="secureChannelProcessor"/>
<ref bean="insecureChannelProcessor"/>
</list>
</property>
</bean>
<bean id="secureChannelProcessor" class="net.sf.acegisecurity.securechannel.SecureChannelProcessor"/>
<bean id="insecureChannelProcessor" class="net.sf.acegisecurity.securechannel.InsecureChannelProcessor"/>
3.To only deliver the login page over HTTPS, we have enabled the SSL/TSL support by generating keystore and enabled the Connector port="8443" in conf/server.xml in the tomcat server
The problem here am facing is, on clicking the j_acegi_security_check request, in Chrome dev tools was showing these attributes 'j_username' and 'j_password' as a plain text under Form Data in the request header.
Am I missing anything here? Kindly help me on encrypt this password or disable this attribute as how it is implemented in the banking applications

Is it the true way to implement spring security & CXF webservice

i create a webservice as below:
web.xml
<display-name>MyService</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/beans.xml,/WEB-INF/spring-security.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!-- Spring Security Filter -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
beans.xml
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
<context:component-scan base-package="com.*" />
<jaxrs:server id="employeeService" address="/employeeservices">
<jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
</jaxrs:providers>
<jaxrs:serviceBeans>
<ref bean="empService" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="xml" value="application/xml" />
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
</jaxrs:server>
<bean id="empService" class="com.service.impl.EmployeeServiceImpl"/>
<bean id="employeeDao" class="com.dao.EmployeeDao"/>
spring-security.xml
<http auto-config="true" use-expressions="true" create-session="stateless" >
<csrf disabled="true"/>
<http-basic entry-point-ref="restAuthenticationEntryPoint"></http-basic>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
</http>
<beans:bean id="userAuthorService" class="com.auth.UserAuthorService"/>
<beans:bean id="restAuthenticationEntryPoint" class="com.auth.UserBasicAuthenticationEntryPoint">
<beans:property name="realmName" value="Name Of Your Realm"/>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userAuthorService">
<password-encoder ref="bcryptPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="bcryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder">
<beans:constructor-arg name="strength" value="5" />
</beans:bean>
<beans:bean id="loggerListener" class="org.springframework.security.authentication.event.LoggerListener"/>
By this configuration, is it flow of request process? :
request -> Spring security(check authentication) -> cxf -> response.
Are there any issues in this configuration when I deploy it in the real sever? what is the standard configuration when using cxf and spring ?
when i call right uri:http://localhost:8089/MyService/rest/employeeservices/getemployeedetals?employeeId=004. its ok.
But call wrong uri: http://localhost:8089/MyService/rest/employeeservices/getemployeedetallll?employeeId=004. It throw exception:
WARNING: No operation matching request path "/MyService/rest/employeeservices/getemployeedetallll" is found, Relative Path: /getemployeedetal, HTTP Method: GET, ContentType: /, Accept: /,. Please enable FINE/TRACE log level for more details.
Jun 07, 2016 1:55:17 PM org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper toResponse
WARNING: javax.ws.rs.ClientErrorException
at org.apache.cxf.jaxrs.utils.SpecExceptions.toHttpException(SpecExceptions.java:110)
at org.apache.cxf.jaxrs.utils.ExceptionUtils.toHttpException(ExceptionUtils.java:149)
at org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:477)
So how can i filter the right uri before access controller class.
Please help me. Thank you.
By this configuration, is it flow of request process? : request ->
Spring security(check authentication) -> cxf -> response.
Yes, because J2EE filters are executed around J2EE servlets (before and after euqeust), so springSecurityFilterChain will be executed before CXFServlet
Are there any issues in this configuration when I deploy it in the
real sever?
This is not necessary with latests versions of CXF
<import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
Also you are catching in CXFServlet /rest/* but in auth *. Is this an issue? Do you need rest services without authentication? Is difficult to analyze issues if we do not know the context of your system. Detail your doubts and I could try to help
what is the standard configuration when using cxf and spring ?
There is no any recommended configuration, because CXF can be used with spring or standalone, jax-ws or jax-rs, as a server or acting as a client, with authentication executed via spring security or integrated with RequestContextFilter or inInterceptor in jax-rs server or even at global level in CXF bus.
If you are talking about the necessary modules to configure so CXF was executed with spring, you have the needed ones.
For authentication, you could consider use a JWT token instead of a bcrypt passwod.
when i call right
uri:http://localhost:8089/MyService/rest/employeeservices/getemployeedetals?employeeId=004.
its ok. But call wrong uri:
http://localhost:8089/MyService/rest/employeeservices/getemployeedetallll?employeeId=004.
It throw exception:
WARNING: No operation matching request path
This warning is normal. The server is responding with an http error code 404-Not found because there is no resource available at rest/employeeservices/getemployeedetallll
So how can i filter the right uri before access controller class.
CXF is doing for you by returning a 404 if the path is not found. It is the correct behaviour. Do you mean CXF uri filter be executed before spring-security? You can not with this configuration because auth filter is previous.

Dispatcher servlet is not able to map my request.I am using spring 2

I have a simple spring application. The basic implementation is, my app will accept the url's .I have a configuration for dispatcher servlet in web.xml. From there the request is handed over to url handler mapping which maps the url to a controller which is configured in application-web.xml. Normal scenarios it works fine
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application-web.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
application-context.xml
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- Integration: URL Mapping for Page controllers START -->
<!-- DEFAULT URL MAPPING -->
<prop key="/*">pasController</prop>
</props>
</property>
</bean>
But for one particular url I am facing issue.
localhost:7001//..................../etc1/passwd
For the above mentioned url, dispatcher servlet is not able to map it to the controller, so because of this request stuck in weblogic level and thread will be stuck.I mean during the mapping process it is getting stuck, container is not able to know what to do.It is not even reaching the application context level.
How to overgo through this situation?Is there any way to play with the above kind of url's. I tried with both spring 2 ang spring3 web mvc jars.

How do I catch Spring errors when starting up a Tomcat webapp?

I have a webapp running in Tomcat which uses Spring for dependency injection. (It's a GWT application, but I don't think that makes much of a difference to the solution I'm looking for.)
My web.xml file is of the following format:
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Servlets -->
<servlet>
<servlet-name>dispatch</servlet-name>
<servlet-class>com.example.my.gwt.dispatch.DispatchServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatch</servlet-name>
<url-pattern>/my_gwt/dispatch</url-pattern>
</servlet-mapping>
... more servlets ...
</web-app>
One of the things my Spring configuration does is to connect to a databse via Hibernate:
<bean id="datasource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driver}" />
<property name="url"
value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="databaseSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="datasource" />
<property name="packagesToScan">
<array>
<value>com.example.my.gwt.model</value>
</array>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
If the database is unavailable, this causes an org.h2.jdbc.JdbcSQLException to be thrown, so the Spring initialisation does not continue, so the rest of the webapp cannot be used. Navigating to the webapp's URL gives an HTTP 503 'Service Unavailable' error.
What I want to do is to catch that error and display a page to the user (when they first navigate to the app) explaining what the problem is likely to be and suggested fixes. How can I do this?
I have tried using a custom ContextLoaderListener class that delegates to the one in the XML above, but catches any exceptions. This allows me to catch the exception, but there is not much I can do - the web.xml is still pointing the user's request to a servlet that is not running after the Spring initialisation has failed. Is there any way that I can change the webapp config when I catch that exception, so that it doesn't try to load the servlets from the web.xml and perhaps changes the welcome file to point to a page about the error? Or is there any other way that I can make the webapp gracefully handle this exception?
Thanks
Basically you're asking if you can have a functioning web application after the web application fails to start up.
You could try configuring a 503 handler page and/or have a welcome page, not dependent on Spring, that checks for something in the application context that's set only on a good spin up. If it didn't spin up, the exception you've already captured could be placed into the app context.
Not sure if anything in the app, even web.xml-only resources, if Spring doesn't spin up, though.
You could add a Servlet Filter to your web app that would intercept all the requests to the Spring servlet and forward to your custom error page if the Spring initialization has failed.

Resources