关于spring security自定义sessionRegistry - jinshiyill - 博客园

最近调了一下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

请先后发表评论
  • 最新评论
  • 总共0条评论