How to get same session with Spring Security and Spring Session From multiple server
It seems like an old question. But, It looks like is possible to achieve the wanted behavior. Check out http://docs.spring.io/spring-session/docs/current/reference/html5/guides/security.html for more details
Create redis beans
<bean id="redisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="port" value="${app.redis.port}" />
<property name="hostName" value="${app.redis.hostname}" />
</bean>
<context:annotation-config />
<bean
class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
The above will create connection to Redis
server with and will create a bean named springSessionRepositoryFilter
which will replace the regular HttpSession
implementation.
Setup spring security
One can create spring filter
via using org.springframework.security.web.FilterChainProxy
i.e :
<b:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<filter-chain-map request-matcher="ant">
<filter-chain pattern="/somelocation/" filters="none" />
<filter-chain pattern="/someotherlocation"
filters="springSessionRepositoryFilter, somemorespring filters"/>
</filter-chain-map>
</b:bean>
Note: The order of the filter for spring security
is important and is not cover in this answer. BUT in order to be able to work with spring Session
and redis, the very first filter has be to springSessionRepositoryFilter
. More info about that can be found at http://docs.spring.io/spring-security/site/docs/3.0.x/reference/security-filter-chain.html
Setting up Http session
Edit web.xml
<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>
This will allow tomcat
to use springSecurityFilterChain
before any filter and therefor it will allow to springSessionRepositoryFilter
to be the first filter. Which will result with the Spring session
magic to get the session
from redis
db
Using Spring session + spring security
with out custom spring filters
can be found at http://www.jayway.com/2015/05/31/scaling-out-with-spring-session/
Lee이민규
Updated on June 12, 2022Comments
-
Lee이민규 almost 2 years
I'm sorry that my english is still not so good. Please bear with me, I hope you can understand my question..
I have two web servers. (each web application is same)
Web servers are sharing one redis server. And I use Spring Security and Spring Session. When I login first server and access second server, I want to login second server automatically, but it isn't.
I guess, because session id is different from different server ip.
- how to get same session id ?
WEB.XML
<!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <!-- Loads Spring Security config file --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/root-context.xml, /WEB-INF/spring/spring-security.xml, /WEB-INF/spring/jedis.xml </param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- Encoding --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>utf-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Session Filter --> <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> <!-- Spring Security --> <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>
jedis.xml
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value=""<!-- My Server IP --> /> <property name="port" value="6379" /> <property name="poolConfig" ref="redisPoolConfig" /> </bean> <bean id="redisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="testOnBorrow" value="true" /> <property name="minEvictableIdleTimeMillis" value="60000" /> <property name="softMinEvictableIdleTimeMillis" value="1800000" /> <property name="numTestsPerEvictionRun" value="-1" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <property name="timeBetweenEvictionRunsMillis" value="30000" /> </bean> <!-- string serializer to make redis key more readible --> <bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" /> <!-- redis template definition --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" > <property name="connectionFactory" ref="jedisConnectionFactory" /> <property name="keySerializer" ref="stringRedisSerializer" /> <property name="hashKeySerializer" ref="stringRedisSerializer" /> </bean>
spring-security.xml
<http pattern="/resources/**" security="none" /> <http auto-config="true" > <session-management session-fixation-protection="changeSessionId"> <concurrency-control max-sessions="1" error-if-maximum-exceeded="true"/> <!-- I couldn't clear understand of this element--> </session-management> <intercept-url pattern="/" access="ROLE_ANONYMOUS, ROLE_USER" /> <intercept-url pattern="/perBoard" access="ROLE_ANONYMOUS, ROLE_USER" /> <intercept-url pattern="/per" access="ROLE_ANONYMOUS, ROLE_USER" /> <intercept-url pattern="/perSearchTag" access="ROLE_ANONYMOUS, ROLE_USER" /> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page="/" authentication-success-handler-ref="loginSuccessHandler" authentication-failure-handler-ref="loginFailureHandler" always-use-default-target="true" username-parameter="j_username" password-parameter="j_password"/> <!-- default-target-url="/board" --> <logout logout-success-url="/" invalidate-session="true" delete-cookies="true" /> </http> <authentication-manager> <authentication-provider user-service-ref="userDetailsService" /> </authentication-manager> <beans:bean id="loginSuccessHandler" class=".......LoginSuccessHandler"> <beans:property name="sqlSession" ref="sqlSession" /> </beans:bean> <beans:bean id="loginFailureHandler" class=".......LoginFailureHandler" /> <beans:bean id="userDetailsService" class="......UserDetailsServiceImpl"> <beans:property name="sqlSession" ref="sqlSession" /> </beans:bean>
-
dragonalvaro over 7 years@durron597 I have the same problems. But I don't have any clue on what's going on. I did the tutorial but they aren't sharing the same session. They are creating a new one.