Spring security 和 Spring session 一起使用

Spring security 中包含对Session的处理,在引入Spring session后,
两者是如何共存的。
有几个问题需要考虑:
1、两者Session存放的位置
2、Session的生命周期管理

第一个问题还没了解清楚,我暂时将问题记录下了,如果有高手知道可以私信我。
疑问如下:
在xml中security配置(session部分)如下:

<security:http>
<security:session-management invalid-session-url="/login.html?error=1" session-authentication-strategy-ref="sas" />
security:http>
<bean id="sas" class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
                <constructor-arg ref="sessionRegistry"/>
            bean>
            <bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"/>
            <bean class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
                <constructor-arg ref="sessionRegistry"/>
            bean>
        list>
    constructor-arg>
bean>
<bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" />

其中SessionRegistryImpl的部分代码:

/**  */
private final ConcurrentMap> principals = new ConcurrentHashMap>();
/**  */
private final Map sessionIds = new ConcurrentHashMap();

明显是将一些user的信息存放在内存中的。
那么SpringSession是将Session信息放到Redis中的,两者矛盾,怎样做才能将SessionRegistryImpl中的信息存放到Redis中?
我能想到的是自己重写这部分,将principals、sessionIds信息写到Redis中。

第二个问题:Session生命周期
在Spring security中通过ApplicationEvent管理生命周期的,而SpringSession在session超时或者被删除时会发送ApplicationEvent。通过代码来看看:
首先在xml中会有如下配置:

 <context:annotation-config/>
    <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
        <property name="maxInactiveIntervalInSeconds" value="300"/>
    bean>

在RedisHttpSessionConfiguration的构造函数中:

    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer(
            RedisConnectionFactory connectionFactory) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(redisSessionMessageListener(),
                Arrays.asList(new PatternTopic("__keyevent@*:del"),new PatternTopic("__keyevent@*:expired")));
        return container;
    }

其中redisSessionMessageListener的类集成了MessageListener接口,熟悉redis的知道,这个接口时redis中的mq的监听接口,也就是说spring session在察觉Session过期或者被删除了的话,会广播一个消息,redisSessionMessageListener就会接受到这个消息,处理这个消息的函数如下:

public void onMessage(Message message, byte[] pattern) {
        byte[] messageChannel = message.getChannel();
        byte[] messageBody = message.getBody();
        if(messageChannel == null || messageBody == null) {
            return;
        }
        String channel = new String(messageChannel);
        if(!(channel.endsWith(":del") || channel.endsWith(":expired"))) {
            return;
        }
        String body = new String(messageBody);
        if(!body.startsWith("spring:session:sessions:")) {
            return;
        }

        int beginIndex = body.lastIndexOf(":") + 1;
        int endIndex = body.length();
        String sessionId = body.substring(beginIndex, endIndex);

        if(logger.isDebugEnabled()) {
            logger.debug("Publishing SessionDestroyedEvent for session " + sessionId);
        }

        publishEvent(new SessionDestroyedEvent(this, sessionId));
    }

上面最后一句就是发送一个SessionDestroyedEvent,这个Event就是ApplicationEvent。再通过如下配置Spring Security就能接收到这个消息了。

1、Spring security可以在通过配置设定超时返回的页面。

<security:session-management invalid-session-url="/login.html?error=1" session-authentication-strategy-ref="sas" />

2、在web.xml中配置

  org.springframework.security.web.session.HttpSessionEventPublisher  

这样spring security会监听session的listener。
到这里就知道Spring Security 和Spring Session是如何协作的了。

以上。

你可能感兴趣的:(配置,Spring)