标签:
最近调了一下spring security的集群session共享,用到了自定义的SessionRegistry,却发现怎么也不工作,翻了翻stackoverfllow,也没找到靠谱的办法,最后自己debug,找到了问题所在
本文基于 Spring3.1.5,Spring security 2.0.4
最开始配置如下:
1
2
3
4
5
6
7
8
9
10
11
|
< beans:bean id = "sessionRegistry" class = "com.shop.core.security.support.SessionRegistryImpl" scope = "singleton" > < beans:property name = "cacheManager" ref = "cacheManager" /> </ beans:bean > < bean:http auto-config = "false" entry-point-ref = "loginUrlEntryPoint" > ... < bean:concurrent-session-control max-sessions = "200000" exception-if-maximum-exceeded = "false" expired-url = "/outline.htm" session-registry-alias = "sessionRegistry" /> ... </ bean:http > |
debug发现自定义的SessionRegistryImpl类也有载入,但是最终系统调用的仍然是原来的
org.springframework.security.concurrent.SessionRegistryImpl
通过阅读源代码发现了其中原因,解释见注释:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public class ConcurrentSessionsBeanDefinitionParser implements BeanDefinitionParser { static final String ATT_EXPIRY_URL = "expired-url" ; static final String ATT_MAX_SESSIONS = "max-sessions" ; static final String ATT_EXCEPTION_IF_MAX_EXCEEDED = "exception-if-maximum-exceeded" ; static final String ATT_SESSION_REGISTRY_ALIAS = "session-registry-alias" ; static final String ATT_SESSION_REGISTRY_REF = "session-registry-ref" ; public BeanDefinition parse(Element element, ParserContext parserContext) { CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); BeanDefinitionRegistry beanRegistry = parserContext.getRegistry(); //这里通过session-registry-ref 去获取自定义的sessionregistry, String sessionRegistryId = element.getAttribute(ATT_SESSION_REGISTRY_REF); if (!StringUtils.hasText(sessionRegistryId)) { RootBeanDefinition sessionRegistry = new RootBeanDefinition(SessionRegistryImpl. class ); beanRegistry.registerBeanDefinition(BeanIds.SESSION_REGISTRY, sessionRegistry); parserContext.registerComponent( new BeanComponentDefinition(sessionRegistry, BeanIds.SESSION_REGISTRY)); sessionRegistryId = BeanIds.SESSION_REGISTRY; } else { //注册默认ID // Register the default ID as an alias so that things like session fixation filter can access it beanRegistry.registerAlias(sessionRegistryId, BeanIds.SESSION_REGISTRY); } String registryAlias = element.getAttribute(ATT_SESSION_REGISTRY_ALIAS); if (StringUtils.hasText(registryAlias)) { beanRegistry.registerAlias(sessionRegistryId, registryAlias); } BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ConcurrentSessionFilter. class ); filterBuilder.addPropertyValue( "sessionRegistry" , new RuntimeBeanReference(sessionRegistryId)); |
也即是说sessionRegistry在做初始化的时候,spring security用了beanRegistry去管理了自身默认的bean的实现,java培训时学到的东西。如果你要使用自定义的,就需要给出相应的配置以取代默认,在BeanIds抽象类里面定义了默认的实现别名,如果获取不到就去获取默认。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public abstract class BeanIds { /** External alias for FilterChainProxy bean, for use in web.xml files */ public static final String SPRING_SECURITY_FILTER_CHAIN = "springSecurityFilterChain" ; /** Package protected as end users shouldn‘t really be using this BFPP directly */ static final String INTERCEPT_METHODS_BEAN_FACTORY_POST_PROCESSOR = "_interceptMethodsBeanfactoryPP" ; static final String CONTEXT_SOURCE_SETTING_POST_PROCESSOR = "_contextSettingPostProcessor" ; static final String ENTRY_POINT_INJECTION_POST_PROCESSOR = "_entryPointInjectionBeanPostProcessor" ; static final String USER_DETAILS_SERVICE_INJECTION_POST_PROCESSOR = "_userServiceInjectionPostProcessor" ; static final String SESSION_REGISTRY_INJECTION_POST_PROCESSOR = "_sessionRegistryInjectionPostProcessor" ; static final String FILTER_CHAIN_POST_PROCESSOR = "_filterChainProxyPostProcessor" ; static final String FILTER_LIST = "_filterChainList" ; public static final String JDBC_USER_DETAILS_MANAGER = "_jdbcUserDetailsManager" ; public static final String USER_DETAILS_SERVICE = "_userDetailsService" ; public static final String ANONYMOUS_PROCESSING_FILTER = "_anonymousProcessingFilter" ; public static final String ANONYMOUS_AUTHENTICATION_PROVIDER = "_anonymousAuthenticationProvider" ; public static final String BASIC_AUTHENTICATION_FILTER = "_basicAuthenticationFilter" ; public static final String BASIC_AUTHENTICATION_ENTRY_POINT = "_basicAuthenticationEntryPoint" ; public static final String SESSION_REGISTRY = "_sessionRegistry" ; public static final String CONCURRENT_SESSION_FILTER = "_concurrentSessionFilter" ; 所以我的配置里面只需要加上session-registry-ref就好了。。 <beans:bean id= "sessionRegistry" class = "com.shop.core.security.support.SessionRegistryImpl" scope= "singleton" > <beans:property name= "cacheManager" ref= "cacheManager" /> </beans:bean> <bean:http auto-config= "false" entry-point-ref= "loginUrlEntryPoint" > ... <bean:concurrent-session-control max-sessions= "200000" exception- if -maximum-exceeded= "false" expired-url= "/outline.htm" session-registry-alias= "sessionRegistry" session-registry-ref= "sessionRegistry" /> ... </bean:http> |
关于spring security自定义sessionRegistry
标签:
原文地址:http://www.cnblogs.com/jinshiyill/p/4635220.html