最近调了一下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>
Original url: Access
Created at: 2019-06-24 10:54:49
Category: default
Tags: none
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
最新评论