java 如何从多个服务器获取与 Spring Security 和 Spring Session 相同的会话
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28447414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get same session with Spring Security and Spring Session From multiple server
提问by Lee???
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 应用程序都相同)
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.
Web 服务器共享一台 redis 服务器。我使用 Spring Security 和 Spring Session。当我登录第一台服务器并访问第二台服务器时,我想自动登录第二台服务器,但事实并非如此。
I guess, because session id is different from different server ip.
我猜,因为会话 id 与不同的服务器 ip 不同。
- how to get same session id ?
- 如何获得相同的会话ID?
WEB.XML
网页.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
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
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>
回答by oak
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.htmlfor more details
这似乎是一个老问题。但是,看起来有可能实现想要的行为。查看http://docs.spring.io/spring-session/docs/current/reference/html5/guides/security.html了解更多详情
Create redis beans
创建Redis bean
<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.
以上将创建与Redis
服务器的连接,并将创建一个名为 bean 的 bean springSessionRepositoryFilter
,该 bean将替换常规HttpSession
实现。
Setup spring security
设置弹簧安全
One can create spring filter
via using org.springframework.security.web.FilterChainProxy
i.e :
可以spring filter
通过使用org.springframework.security.web.FilterChainProxy
ie创建:
<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
注意:过滤器的顺序spring security
很重要,本答案不包括在内。但是为了能够使用 spring Session 和 redis,第一个过滤器必须是springSessionRepositoryFilter
. 有关更多信息,请访问http://docs.spring.io/spring-security/site/docs/3.0.x/reference/security-filter-chain.html
Setting up Http session
设置 Http 会话
Edit web.xml
编辑 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
这将允许在任何过滤器之前tomcat
使用springSecurityFilterChain
,因此它将允许springSessionRepositoryFilter
成为第一个过滤器。这将导致从dbSpring session
获取的魔法session
redis
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/
使用Spring session + spring security
带出来custom spring filters
,可以发现http://www.jayway.com/2015/05/31/scaling-out-with-spring-session/