☰
Redis密码设置全攻略:从requirepass到ACL的实战避坑指南
2026/9/28 7:42:25 网站建设 项目流程

前阵子帮朋友排查一台服务器,刚登上去就发现不对劲:Redis端口在公网暴露着,进程还活着,但数据库里多了一堆莫名其妙的key,crontab里被塞了定时任务,一看就是被自动化脚本盯上了。这台Redis压根没设密码,属于“裸奔”状态。朋友知道后问我:“Redis密码设置不就一行requirepass的事吗?还能有什么坑?”——这句话其实代表了大多数人的认知。

确实,单看“设置密码”这个动作,一行配置就完事了。但把这行配置放进生产环境,会发现后面还牵着一串问题:密码怎么跟主从同步、哨兵、集群协作?客户端连接参数怎么配?分布式锁、Lua脚本在鉴权下怎么跑?密码在日志、历史命令、配置文件里会不会被泄露出去?这些才是“Redis密码设置”真正值得写一篇长文的地方。这篇文章会从最基础的requirepass讲起,一路覆盖到高可用架构和Redis 6的ACL精细权限,适合刚接触Redis的新手,也适合已经在生产环境用Redis、想回头查缺补漏的开发者或运维。

1. 先算一笔账:Redis裸奔到底有多危险

1.1 那个被当成肉鸡的Redis实例

先说朋友那台服务器的事。根因很快查清:Redis监听在0.0.0.0:6379,没有任何访问控制,所有命令裸奔。攻击者连上来之后,直接用CONFIG SET

设置了dir和dbfilename,把一段恶意数据写成了crontab任务。从那之后,这台机器每隔几分钟就去拉取一段挖矿脚本,CPU占用长期飘在80%以上。

这不是个别案例,而是互联网上每天都发生的事。Redis默认不鉴权,如果你装完redis-server就直接扔到公网或者干脆没做任何网络层隔离,那等同于把一个装满档案的抽屉摆在路边,谁路过都能翻。更麻烦的是,Redis的命令非常灵活,攻击者不只会读数据,还能通过主从复制加载自定义模块、写入计划任务、覆写系统文件,这些技术细节网上都有讨论,但核心就一句:未授权访问的Redis,等于把服务器最高权限的半把钥匙交了出去。

1.2 攻击者的三条典型入侵路径

很多人觉得“我的Redis里只有不重要数据,被删了也无所谓”。这种想法在真实攻击里站不住脚,因为攻击者盯上的不是你那几个key,而是整台服务器:

  • 写定时任务:利用CONFIG SET dir和CONFIG SET dbfilename,结合SAVE/BGSAVE把构造好的数据写到 /var/spool/cron/ 或 /etc/cron.d/ 下,从而拿到周期性执行命令的能力。这是“Redis未授权访问拿服务器权限”里最经典的打法。
  • 写公钥文件:把攻击者的SSH公钥写入 /root/.ssh/authorized_keys,之后直接通过SSH密钥登录,获得完整shell。
  • 加载恶意模块:Redis 4.0之后支持MODULE LOAD,攻击者可以复制一个恶意的so文件到服务器,再让Redis加载,执行任意命令。

这三条路径的共同前提都是能连上Redis且无需密码。一旦配置了requirepass,第一道门槛就把绝大多数自动化扫描脚本拦在门外了。不能保证百分百安全,但攻击成本会被拉高一个数量级。

1.3 设密码前的现状评估

动手设置密码之前,建议先梳理一下Redis实例的当前访问方式,而不是闷头改配置。我会按这个顺序做一遍整体评估:

  1. 用INFO或CLIENT LIST看看当前有哪些应用在连接,IP和端口都记下来。
  2. 确认Redis部署形态:单机、主从、Sentinel还是Cluster,不同的形态决定后面密码参数往哪儿配。
  3. 确认访问Redis的客户端类型:命令行、Spring Boot/Node/Python应用、可视化工具、还有定时任务里跑的脚本。
  4. 确认是否已经存在主从关系:如果有从节点,只改requirepass不够,还要改masterauth,否则密码一上,主从同步直接断。
  5. 检查现有的防火墙/安全组规则:6379端口是否只对可信IP开放。

这一步千万别省。我在很多生产环境里看到过改完requirepass后,主从同步断了半天没人发现,原因就是没提前做现状评估。下面进入正题,说说密码到底怎么设。

2. 设置密码的三条路径:配置文件、命令行与启动参数怎么选

Redis设置密码的方法有三条,分别对应不同的使用习惯和运维场景。很多教程只提配置文件那条,但实际运维中,尤其是容器化部署和临时调试时,后两条更常用。

2.1 通过redis.conf设置requirepass

最基础、也最推荐的方式是在配置文件里加上一行:

requirepass YourStrongPassword2025

然后重启Redis或者用其他方式重新加载配置。注意requirepass在配置文件里就是这样的写法,大小写不要写错。新版Redis虽然语法没变,但配置文件改名或者注释位置不同,容易让人一脸懵。我通常把它放在SECURITY段落下面,和后面的rename-command之类安全配置放在一起,方便日后维护。

这里有个容易踩的小坑:如果配置文件里已经有了一个被注释掉的# requirepass foobared,你直接写一个新行没问题,但最好把原来的注释行删掉,避免有人粗心看到两行混淆。设置完后,用redis-cli -a 密码或者redis-cli之后执行AUTH来验证就对了。

2.2 动态设置:CONFIG SET与CONFIG REWRITE的搭配

不重启Redis就启用密码,用CONFIG SET:

redis-cli CONFIG SET requirepass "YourStrongPassword2025"

这种方式立刻生效,适合线上实例不想重启的场景。但要记住:CONFIG SET修改的只是运行时配置,不会自动写回配置文件。如果哪天Redis重启了,密码会直接消失,回到裸奔状态。

所以动态设置之后,要执行一次:

redis-cli -a YourStrongPassword2025 CONFIG REWRITE

CONFIG REWRITE会把当前运行配置写进原有的配置文件。前提是Redis能以对应权限启动时的用户去写这个文件,如果配置目录权限不对,它会静默失败。因此,改完配置后建议马上查看一下配置文件内容确认,或者重启一次Redis做稳定验证。

2.3 启动参数--requirepass的正确打开方式

第三种是启动时直接带参数:

redis-server --requirepass YourStrongPassword2025

这种方式在临时实例、测试环境或者命令行启动Redis时非常方便,不需要准备配置文件。但缺点也明显:启动参数会出现在shell的history里和设备系统日志中。在服务器管理工具、systemd服务文件里也可能被记录,安全性打了折扣。

我个人只有在本地开发环境才会这样用,生产环境一律走配置文件。另外,如果你用手写systemd unit文件启动Redis,务必看下ExecStart那行有没有把密码参数暴露出去,历史记录清一下比较好。

2.4 三种方式的优先级与适用场景总结

设置方式是否持久化推荐场景注意事项
redis.conf中的requirepass持久生产环境所有实例修改需重启或加载配置
CONFIG SET requirepass不持久线上实例临时调整需配合CONFIG REWRITE
--requirepass启动参数随启动方式而定开发测试、容器启动注意命令历史和日志泄露

前面提到容器化部署,现在很多人在Docker里跑Redis。使用官方redis镜像时,通常用两种方式之一传密码:一是-v挂载配置文件进去,并在配置里写requirepass;二是用启动命令拼接:

docker run -d --name redis \ -p 6379:6379 \ redis:7 redis-server --requirepass YourStrongPassword2025

在Docker Compose里也可以写成command: redis-server --requirepass YourStrongPassword2025。但同样是那个问题:如果密码写在compose文件里,务必确保这个文件在仓库里做了脱敏或者访问权限受限。

3. 密码设置后的连接方式:命令行、代码客户端与可视化工具全适配

密码设好只是第一步。接下来各种客户端连接不上,才是一连串问题的开始。这块的内容你在Redis官网文档里能看到基本API,但真实参数细节和坑,文档里可不会全部提到。

3.1 redis-cli:-a参数与交互式AUTH

最直接的验证方式:

redis-cli -a YourStrongPassword2025 PING

这时会返回PONG,同时cli会打印一行警告,大意是“使用命令行参数传递密码不安全,其他用户可能通过ps看到”。如果你在一个多人共享的服务器上执行这条命令,确实会被别人通过ps aux看到明文密码。有两种办法缓解:一是用交互方式连接然后再AUTH:

redis-cli AUTH YourStrongPassword2025

二是设置环境变量:

export REDISCLI_AUTH="YourStrongPassword2025" redis-cli PING

设置了REDISCLI_AUTH之后,redis-cli会自动完成认证,而且密码不会出现在命令行参数里,比-a稳妥得多。我在脚本里也倾向用环境变量,或者在脚本头部用read读取密码文件,而不是死写在脚本里。

3.2 代码客户端(含Python/Java)如何传密码

在Python的redis-py里,连接参数的写法非常直观:

import redis r = redis.Redis( host="127.0.0.1", port=6379, password="YourStrongPassword2025", db=0 ) print(r.ping())

如果是连接池:

pool = redis.ConnectionPool( host="127.0.0.1", port=6379, password="YourStrongPassword2025", max_connections=20 ) r = redis.Redis(connection_pool=pool)

Java这边,用Jedis时很多人踩过坑。Jedis的构造方法里new Jedis(host, port)是无密码的,必须显式调用auth或者通过JedisPoolConfig配合创建连接池时塞入密码:

JedisPool pool = new JedisPool( new JedisPoolConfig(), "127.0.0.1", 6379, 2000, "YourStrongPassword2025" );

Spring Boot的spring-boot-starter-data-redis也一样,在application.yml中配置:

spring: data: redis: host: 127.0.0.1 port: 6379 password: YourStrongPassword2025

注意Spring Boot 2.x和3.x的属性前缀略有不同,2.x用spring.redis.password,3.x用spring.data.redis.password。如果你升级了Spring Boot突然一连就报NOAUTH Authentication required,先检查这里。

3.3 可视化客户端:Redis Desktop Manager等工具配置

热词里也看到了Redis Desktop Manager、Another Redis Desktop Manager这些工具。这类可视化客户端连接配置很相似:

  • 地址填Redis服务器IP,端口默认6379。
  • 认证填密码,不同工具叫法略有差异,有的是Password,有的是Auth。
  • 如果Redis还配置了ACL用户,需要填用户名,默认是default。

远程连接带密码的Redis,我建议一定要另外勾选SSL/TLS选项。如果没有启用TLS,密码走明文传输,内网还能接受,跨公网就非常危险。另一件事是生产环境尽量避免使用可视化工具,至少不要把生产数据库配置信息长留在工具里,否则工具一旦被植入恶意代码或者电脑被盗,等于把钥匙串整个交出去。

3.4 连接出现NOAUTH时的排查思路

给Redis设置密码后,最常见的报错是NOAUTH Authentication required。排查链路大概是:

  1. 先确认密码确实设置上了:本地跑CONFIG GET requirepass,看返回值是否非空。
  2. 确认客户端确实传了密码:逐一检查连接池参数、配置文件、环境变量。
  3. 如果用的连接池,确认池是否创建于设置密码之前。有些长连接是旧连接,可能没经过认证,需要让连接池重建连接。
  4. 如果是多台应用服务器,确认所有应用都改了配置,漏掉一台就会单独报错。
  5. 看Redis日志,Redis会打印客户端的IP,能帮你定位是哪台机器没配置对。

4. 高可用架构下的密码坑:主从复制、Sentinel与Cluster的密码传递

单机设密码简单,一旦进入主从、哨兵、集群,密码配置立刻翻几倍复杂度。这几块我踩坑踩得最多,也见到生产事故最多。

4.1 主从复制中的masterauth为什么比requirepass更关键

主从架构中,requirepass只控制客户端访问Redis时需要AUTH。从节点主动连接主节点做同步时,走的不是普通客户端鉴权路径,而是单独的密码参数:masterauth。

如果只配了主节点的requirepass,没配从节点的masterauth,从节点会连接主节点时报MASTER auth failed,然后每隔一段时间重试一次,数据自然就一直保持不了同步。配置方法是在从节点的redis.conf里也加:

requirepass 你的密码 masterauth 你的密码

注意从节点自己也要设置requirepass,否则从节点会成为架构里的防守漏洞。很多和我做过排查的人都说:主从复制断开了吗?同步日志拉出来一看,十有八九是masterauth忘了配。

4.2 Sentinel的sentinel auth-pass配置位置

Redis Sentinel的高可用架构里,Sentinel本身要连接主从节点去检查状态,所以Sentinel的配置文件也需要密码信息。常见的错误是只给Redis配了密码,Sentinel进程一直用无密码方式探测,于是日志里全是-NOAUTH或者无法ping通主节点。

需要在每个Sentinel节点的配置文件(sentinel.conf)中写上:

sentinel monitor mymaster 127.0.0.1 6379 2 sentinel auth-pass mymaster YourStrongPassword2025

第二行的mymaster必须和第一行的master name完全一致。更重要的是,如果主从节点都配置了requirepass,Sentinel也只能连上后才能做后续操作。当发生故障转移时,升级为新的主节点的节点,它的requirepass和masterauth都会保留,Sentinel继续用auth-pass里的密码去连,这样才能保障切换后整个单元依然可用。

4.3 Cluster模式下的多节点密码同步

Redis Cluster环境下,每个节点都要配置requirepass和masterauth。一般做法是让所有节点使用相同密码,并且在配置文件里都加上这两行。cluster管理命令在加密码后,节点之间通信和握手时会用masterauth进行认证。如果集群节点间密码不一致,会出现ERR invalid password或者cluster状态一直是fail的奇葩问题。

我用一个土办法来验证集群密码是否统一:

redis-cli -c -h node1 -p 6379 -a 密码 CLUSTER INFO

看返回结果中的cluster_state是不是ok,以及各个节点日志中是否出现auth失败记录。密码统一是集群的基本卫生条例,别想着给节点搞差异化密码,那是自找麻烦。

4.4 主从切换后写入失败的真实案例复盘

之前帮一家公司排查过这么个案例:某次Sentinel故障转移完成,新主节点已经提升,从节点开始重连。业务那边大量出现READONLY You can't write against a read only replica。日志里看,新主节点明明处于master状态,却还在拒绝写入。

最后定位到的原因非常典型:新主节点是原来的从节点,它的配置文件里masterauth指向的是老主的密码,但它在提升为master后,并不需要masterauth;而业务连接的密码字符串比配置的多了一个换行符——挂在配置中心里的时候,密码末尾被粘贴进了多余的空白字符。客户端每次AUTH时,密码里带着\n,老实例居然能接受,因为老实例密码长度校验相对宽松?不是,真正原因其实是新主节点的auth校验逻辑发现密码不匹配。这个案例后来处理方式是整理配置中心里的密码,统一去掉了异常空白。

还有个小细节必须说:高可用架构里改密码,一定要梳理好“先改从、再改主、再改Sentinel配置”的顺序。如果先改主,从节点会断同步;如果先从从节点改,主节点暂时不受影响。我自己习惯先用CONFIG SET对从节点和主节点都更新一遍,再更新配置文件和Sentinel,最后用CONFIG REWRITE固化,尽可能降低窗口期。

5. 密码与业务场景联动:分布式锁和Lua脚本的鉴权细节

生产环境里,Redis密码设置之后,受影响的除了普通读写,还包括分布式锁、Lua脚本这类进阶用法。这里面的细节很少有人在“设置密码”教程里讲清楚,但恰恰是业务代码里最容易翻车的地方。

5.1 分布式锁客户端(Jedis/Redisson)的密码参数传递

先看Redisson——Spring Cloud生态下分布式锁很常用。Redisson创建客户端时如果不给密码,程序不会立刻报错,而是到获取锁那一步才开始报NOAUTH或权限异常。配置方式在YAML里:

redisson: singleServerConfig: address: redis://127.0.0.1:6379 password: YourStrongPassword2025

Jedis做分布式锁通常需要自己封装一套SET NX EX逻辑。很多人直接用new Jedis(host, port)创建连接,忘了密码,锁操作就失败。加密码的写法刚才已经提到,用带Password参数的构造器。还有一点,如果Redis配置了ACL,Redisson还支持username字段,这是被很多人忽略的:

redisson: singleServerConfig: username: default password: YourStrongPassword2025

5.2 Lua脚本执行是否需要单独鉴权

Redis的Lua脚本是通过EVAL或EVALSHA执行的,本身不涉及额外的一套鉴权机制,但有两个需要注意的点:

  • 连接必须已经完成AUTH认证,否则任何EVAL都会返回NOAUTH。
  • Lua脚本内部的redis.call('GET', key)等操作,用的是已认证连接的权限,不需要在脚本里重新传密码。

实际操作中,我用Spring Data Redis执行Lua脚本,最常见的错误是脚本内容没问题,但连接没带密码,报错和处理普通命令一样。还有一点:如果你在Redis事务或者管道里执行Lua,同样是在同一个连接上,鉴权状态延续,不需要重复AUTH。

很多人会问,设置密码能不能限制Lua脚本执行危险命令?答案是不行,只要认证成功,脚本里就可以调用所有允许的命令。要想按业务隔离权限,就得用Redis 6的ACL,这个我放到下一节讲。

5.3 设置了密码后,连接池和缓存的兼容性注意

密码设置后,缓存和连接池的兼容性也会引发怪现象。比如Spring Boot的缓存模块通过Lettuce连接Redis,如果在配置了密码后仍使用LettuceConnectionFactory默认无密码构造,会出现能启动但不一定能操作缓存的诡异状态。因为Lettuce是懒连接,真正执行缓存操作才去建连接,那时候报NOAUTH。

排查这类问题,我一般两步走:

  1. 看启动日志里是否出现Redis连接相关的exception。
  2. 用spring-boot-starter-actuator的health端点检查Redis health状态,报RedissonConnectionFailureException或RedisConnectionFailureException,基本可以定位到鉴权配置。

连接池方面,JEDIS和Lettuce都存在“池内连接”和“密码参数”耦合的问题。修改密码后,连接池里残留的未认证连接往往不会自动重建。有些连接池会通过testOnBorrow参数去校验连接是否可用,如果没开,就会出现偶发性的NOAUTH。处理办法是在连接池配置里开启合理的校验机制,或直接重启应用。这属于在生产环境切换Redis密码时的隐藏雷区,值得提前打预防针。

6. 从requirepass到ACL:Redis 6的精细权限控制

聊到这儿,你会发现requirepass只能实现对Redis整体访问的口令控制,功能上比较“一刀切”。不管你是谁,只要密码对了,想执行什么命令都可以。这在多业务共用一个Redis实例的环境中特别危险。Redis 6引入ACL(Access Control List)之后,权限控制的粒度才真正细化到“用户+命令+Key级别”。

6.1 ACL是什么,和requirepass有什么区别

简单理解,requirepass相当于一把总钥匙,ACL相当于一堆分控制卡。传统requirepass模式下,所有客户端共享同一个密码,A应用能执行的命令,B应用只要拿到同样密码也能执行。ACL模式下,你可以创建不同用户,每个用户拥有独立的密码、独立的命令白名单、独立的可访问key范围。

比如业务A只能读某个前缀的key,业务B只能执行SET/GET,运维账号才能执行CONFIG、SHUTDOWN这类敏感命令。这让密码设置的边界更小,更贴近最小权限原则。

6.2 快速上手:ACL SETUSER创建专用账号

Redis 6之后,创建用户的基本语法:

ACL SETUSER biz_readonly ON > BizOnlyPass2025 ~cache:* +@read

解释一下这段:

  • ON表示激活该用户。
  • >BizOnlyPass2025设置密码。
  • ~cache:*限制只允许访问以cache:开头的key。
  • +@read允许所有读类命令。

客户端用这个账号连接时,需要在AUTH时指定用户名:

AUTH biz_readonly BizOnlyPass2025

在Spring Boot里,用户名和密码可以分别配置:

spring: data: redis: username: biz_readonly password: BizOnlyPass2025

这里要说个细节:即使你只配置了requirepass,Redis内部也等于存在一个default用户,密码就是这个requirepass。ACL设置时如果对default用户做修改,会影响所有使用传统密码方式的客户端。所以平滑过渡时,最好先为每个业务建好ACL用户,切换客户端,最后再收紧default用户权限。

6.3 平滑迁移建议:从单一密码到多用户权限

如果你现在还在用requirepass,想要迁移到ACL,我建议按以下步骤:

  1. 先用ACL LIST查看当前用户情况,备份好default用户设置。
  2. 逐业务创建ACL用户,密码尽量用独立随机串,不要大家共用一个。
  3. 客户端配置逐步切换用户,灰度发布,观察业务日志。
  4. 确认所有客户端都切走后,再把default用户取消密码或删除敏感命令权限,防止它成为后门。

迁移代价并不小,但收益也很明显:一旦某个业务的密码泄露,攻击者拿到的只是一个受限账号,而不是整个Redis实例。

补充一个ACL的恢复技巧:如果不小心把自己锁在Redis外面了——比如把default用户的超级权限删了——只要底层用户还有系统权限,可以直接改配置文件里的user default行,或者在文件里临时重置ACL规则。如果Redis没有开启保护模式且是内网环境,也可以直接改配置文件然后重启。总之,做ACL实验时,千万别在唯一的运维连接上缩紧到连认证都过不了,最好先保留一个高权限的备用用户。

最后再分享几个我长期在用的密码管理习惯

密码设置不是配一次就一劳永逸的事。我自己的习惯大致是:

  • 密码尽量由随机生成器产生,不包含字典词,长度至少16位以上。运行在公网环境的重要实例,甚至会用密码管理工具生成独立的随机串。
  • 为每套环境独立设密码。测试环境、预发环境、生产环境建议不要用同一个密码,不然一处泄露,处处危机。
  • 配置文件权限收紧。redis.conf和部署目录尽量用单独的用户,避免任意用户可读。如果密码不得不放在Spring的配置文件或K8s Secret里,记得配合平台的密钥管理能力去处理,别用明文提交到代码仓库。
  • 定期轮换密码,每次轮换前写好变更清单,包括客户端、主从、哨兵、集群节点、可视化工具等所有访问入口。轮换后用一个简单的redis-benchmark -a或者健康检查接口验证一遍。
  • 关注Redis日志的warn级别输出,连接密码错误都会留下记录,方便发现是否有暴力破解尝试。

写到这里,回头看“Redis密码设置”这件事,已经远不止“一行requirepass”那么简单。从单机裸奔的防御,到客户端连接适配,再到高可用架构的密码传递,最后到ACL权限模型的落地,每一步都有现实的踩坑教训在里面。希望这篇内容能帮你把Redis的访问控制补得扎实一点,至少下次再遇到那台“裸奔”的Redis,你能第一时间想起,哦,密码这个环节不仅仅是加一行配置那么简单。如果你还在用老版本Redis,连ACL都还不支持,建议认真考虑升级,毕竟现在所有必要的新安全能力,基本都集中在6.0往后的版本上了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询