微人事-spring security session与servlet里session的区别

前言

上一节实现session并发的时候,注意到一个细节

//注册session
sessionRegistry.registerNewSession(request.getSession(true).getId(), principal);

为什么要手动注册一个session呢,web服务器不是默认给每个独立的请求创建一个session吗?不注册的话,会怎么样?

分析

(1)首先先聊下web服务器里的session创建时机,当一个新的请求到来时,HttpSessionListener接口(实现的监听器)的sessionCreated方法就会被调用,为之创建一个session。

/**
	 * Handles the HttpSessionEvent by publishing a {@link HttpSessionCreatedEvent} to the
	 * application appContext.
	 *
	 * @param event HttpSessionEvent passed in by the container
	 */
	public void sessionCreated(HttpSessionEvent event) {
		HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession());
		Log log = LogFactory.getLog(LOGGER_NAME);

		if (log.isDebugEnabled()) {
			log.debug("Publishing event: " + e);
		}

		getContext(event.getSession().getServletContext()).publishEvent(e);
	}

(2)测试来验证下

@Configuration
public class HttpSessionConfig {
    private static final Map<String, HttpSession> sessions = new HashMap<>();

    public List<HttpSession> getActiveSessions() {
        return new ArrayList<>(sessions.values());
    }

    @Bean
    public HttpSessionListener httpSessionListener() {
        return new HttpSessionListener() {
            @Override
            public void sessionCreated(HttpSessionEvent hse) {
                sessions.put(hse.getSession().getId(), hse.getSession());
            }

            @Override
            public void sessionDestroyed(HttpSessionEvent hse) {
                sessions.remove(hse.getSession().getId());
            }
        };
    }
}

每建立起一个会话就会创建一个session
在这里插入图片描述
(3)spring security session的创建时机有4种

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
}

always – 如果session不存在总是需要创建;
ifRequired – 仅当需要时,创建session(默认配置);
never – 框架从不创建session,但如果已经存在,会使用该session ;
stateless – Spring Security不会创建session,或使用session;

举例:如果设置成always,判断的地方是在SecurityContextPersistenceFilter#doFilter

if (forceEagerSessionCreation) {
			HttpSession session = request.getSession();
			if (debug && session.isNew()) {
				logger.debug("Eagerly created session: " + session.getId());
			}
}

参考:spring security控制session
(4)所以spring security默认是不会自动创建session,但是spring security里面提供了注册session的方法SessionRegistryImpl#registerNewSession,session是交由SessionRegistryImpl去管理。下面是注册session的方法

sessionIds.put(sessionId,
				new SessionInformation(principal, sessionId, new Date()));

可以看到这里存储的session其实是SessionInformation,并不是web容器里的HttpSession,这是两个不同的session,要注意区分
(5)到这谜团解开了,SessionRegistryImpl是security提供来管理SessionInformation的,所以如果我们不手动注册,则SessionRegistryImpl#getAllPrincipals永远为空即注册表里永远为空,这样也就无法实现session的并发处理。

总结

这是自己翻看源码的理解,若有错误请及时联系我更正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值