首页 文章详情

记一次Shiro+Redis分布式多台机器session会话不共享问题的排查!

业余草 | 108 2022-07-16 12:53 0 0 0
UniSMS (合一短信)

你知道的越多,不知道的就越多,业余的像一棵小草!

你来,我们一起精进!你不来,我和你的竞争对手一起精进!

编辑:业余草

推荐:https://www.xttblog.com/?p=5351

记一次Shiro+Redis分布式多台机器session会话不共享问题的排查!

话说公司一个老项目,突然来了几个需求。时间紧迫,于是就安排了一个小团队去完成。历时 2 月有余,功能终于做完了。测试发了测试报告,约定了周五晚上上线。

到了周五这天,我是早早的摸鱼下班了。上海疫情这么严重的情况下,我还是出去吃了一次烧烤。晚上 10 点,刚到家。老项目的小团队负责人,给我打电话了。

“草哥”,生产环境无法登录了?你快帮我们看看吧。

我心里,顿时有了一种不好的预感。我先打开生产环境的地址,输入帐号密码进行登录。发现登录成功后,没有正常跳转到首页。

无限循环的登录

这怎么可能会出问题呢?这个功能测试都不能发现有问题么?测试环境不都是好的吗?sit、uat 都是好的,怎么生产就出问题了呢?

代码都是一样的,但是生产却出了问题。于是乎,我想到了可能是运维对几个环境的 nginx 配置不同导致的。

所以,我直接联系了运维,直接让他把应用程序的端口放开。

然后,我直接在电脑上访问http://www.baidu.com:10003/。输入帐号密码等一顿操作之后,发现完全没毛病,可以正常登录。所以,我把锅甩给了运维。让他赶紧排查一下,看看 nginx 的配置。然后,我就下线了,不想被他们打扰。

第二天,周六早上,我打开手机一看。满屏的消息,都在 @ 我。我一看消息,这帮人,搞到了凌晨 3 点,还没把问题修好。

我暗自庆幸,还好我昨晚睡的早,要不然,头发又要掉一堆。

这帮人,昨晚发布失败后,直接回退了代码。于是等到上午 10 点钟以后,我问他们为什么发布失败了?他们说登录问题还是没解决!

运维什么时候这么窝囊了!我心里暗自猜想,于是我有直接联系了运维,了解具体情况。

运维说:“sit、uat 都重现了。生产是 8 台,测试环境都是 1 台机器。现在我把测试环境都改成集群部署,测试环境都重现出了问题”

于是,我找到了老项目的负责人,负责人说没查出来是什么问题。他需要比对代码,再给我结论。

这负责人是咋上位的

天呐,这负责人是咋上位的?这两个月写了多少代码,需要比较多久,能一定找出原因吗?

我猜他肯定是因为写代码不行,才上位的。因为,他头发好像也不多。。。

我作为架构组的一员,肯定不能让他这么糊涂下去。

于是,我拦住了他。不用比对了,你休息去吧,我来排查。

问题原因

根据他们的问题描述,我的直觉告诉我,应该是多台机器的 session 共享问题。

老项目使用的是 shiro 框架,这段时间应该有人动了这块的代码。于是我更新了老项目,搜索 shiro 相关的配置。发现确实有人改了,于是我根据改动人的提交,找到了当事人。

原来是 shiro 原来的旧包有漏洞,所以,他做了升级。升级后,旧的 api 被移除了。他使用了新的 api,但没想到会影响到登录功能。

于是,我查看官方文档,改动了 3 行代码就修复了。

@Bean(name = "webSecurityManager")
public DefaultWebSecurityManager securityManager(RedisCacheManager cacheManager, UserRealm userRealm, ServletContainerSessionManager defaultWebSessionManager, IRedisManager redisManager, Authenticator authenticator){
 DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    manager.setRealms(Arrays.asList(userRealm, systemAuthorizingRealm(cacheManager)));
    manager.setAuthenticator(authenticator);
    // ...
}

新代码:

@Bean(name = "webSecurityManager")
public DefaultWebSecurityManager securityManager(RedisCacheManager cacheManager, UserRealm userRealm, IRedisManager redisManager,
                                                 RedisWebSessionManager defaultWebSessionManager,
                                                 Authenticator authenticator)
 
{
    RedisSessionDAO a = new RedisSessionDAO();
    a.setRedisManager(redisManager);
    defaultWebSessionManager.setSessionDAO(a);
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    manager.setRealms(Arrays.asList(userRealm, systemAuthorizingRealm(cacheManager)));
    manager.setAuthenticator(authenticator);
    // ...
}

就这。。。

就这么简单,就这么一点小问题。还需要比对整个项目最近两月的提交?搞到凌晨 3 点都还没解决!

本篇文章没啥技术含量,也没别的意思,就是记录一下,方便其他网友在使用 shiro + reidis 时,多台机器无法 session 回话共享问题!

不喜轻喷!!!

good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter