前言
这几天,公司做了很多安全方面的检查。对代码和中间件,做了非常详细的扫描。
代码我们前几天已经处理了。
单发现缓存:Redis有安全漏洞。
当时运维同学为了方便,在程序中连接Redis时,不需要登录密码就能直接访问。
这个漏洞,这次被发现了要及时解决。
为了保证Redis服务器的高可用,我们目前使用了Sentinel的哨兵机制。
这次在访问Redis和Sentinel时,分别设置了访问密码。
但上线之后,生产环境出现了一个非常致命的问题。
到底怎么回事呢?
案发现场
今天上午发现,我昨天修改的一个发票服务,出问题了。
从sentry中查到了很多报警邮件,打印的日志如下:
ERR Client sent AUTH, but no password is set.程序访问不了Redis服务器。
日志中提示说没有设置密码,但其实已经设置过密码了。
打开相关的页面,发现登录不了。
登录功能是需要访问Redis的,但是Redis加了访问密码之后,访问不了,所以导致了登录功能的问题。
其实,这次改动非常小,我只在配置文件中增加了下面两行配置:
spring.redis.password=123456
spring.redisson.config={"sentinelServersConfg":{"sentinelAddress":["redis://test1:26379","redis://test2:26379","redis://test3:26379"],"masterName":"myMaster","database":1,"password":"123456"}}调整之后,部署到测试环境,测试了,登录功能OK,并且查看了Redis的数据库,看到数据也正常写入了。
这就很奇怪了。。。
我们给Redis设置了密码之后,当时测试票据服务没有问题,然后就没管了。
没想到在一个小时之后,出现了问题。
分析问题
刚开始,我以为是票据服务的生产环境的配置配错了。
但仔细核对相关的信息之后,确认配置没有问题。
票据服务是一个老项目,从其他团队的人手上接手过来的。
它的代码结构,使用的技术栈,跟我们其他的项目有区别,虽然都是用的SpringBoot、SpringCloud那一套东西。
但它使用的SpringBoot的版本,跟其他的项目不一样。
这个项目使用的yml配置文件,其他的项目使用的properties配置文件。
刚开始,我以为在yml文件中不能配置spring.redisson.config这种json格式的数据。
调整成yml格式之后,发现还是不行。
接着猜测,可能这个项目用不到spring.redisson.config配置。
于是,把它去掉了,任然不行。
后来,仔细对比了测试环境和生产环境代码的差异。
发现配置文件是一样的。
但有个非常奇怪的现象,测试环境功能正常,生产环境功能异常。
还有一个更奇怪的现象:其他的访问Redis的业务系统功能已都正常。
一下子把我整懵了。。。
解决问题
既然其他的业务系统功能正常,要不对比一下,跟票据系统的代码差异?
配置文件是一样的。
唯一有差别的是SpringBoot的版本。
票据系统是一个老项目,使用SpringBoot老的版本。
使用的redisson-spring-boot-starter的版本是3.10.6,而其他项目使用的版本是3.17.7。
要不升级一下redisson客户端的版本?
果然升级后一下子解决问题了。
后续
线上Redis访问不了的问题被解决了。
但为什么测试环境的功能正常,而生产环境的功能出现问题呢?
这个问题让我百思不得其解。
后来,运维同学解释说,测试环境Redis密码验证关闭了,不管设不设置密码,都能够正常访问Redis。
我去,被坑了一把。因为当时项目中的配置修改完之后,我在测试环境仔细测过,没有问题,才发布的生产环境。
其实,很多问题说来说去,不是配置的问题,不是代码的问题,有可能是引入的开源jar包的版本问题,这类问题我最近已经遇到过很多次了,请大家后面务必要引起重要。