1. 从一次线上告警说起NOAUTH 到底在报什么凌晨两点监控群里弹出一条告警某个业务服务的 Redis 操作全部失败日志里清一色刷着(error) NOAUTH Authentication required。值班的同事第一反应是Redis 挂了重启了一遍服务结果照旧。折腾了半小时才反应过来——不是 Redis 挂了是客户端没带密码。这个报错其实特别直白翻译成人话就是你连上了 Redis但你想执行命令的时候服务端说你还没证明你是谁。注意这里的关键词是连上了。很多人会误以为这是连接失败其实不是。TCP 握手是成功的Redis 服务端也接受了你的连接只是在你发第一条实际命令比如GET、SET、PING的时候服务端检查发现当前连接没有通过认证于是拒绝执行并返回这个错误。要理解这个机制得先知道 Redis 的认证是怎么回事。Redis 从很早的版本就支持一个叫requirepass的配置项一旦在配置文件里设置了它服务端就进入了需要认证模式。此时任何客户端连接上来都必须先发送AUTH password命令认证通过之后才能执行其他命令。如果没认证就直接发命令服务端就会回NOAUTH Authentication required。这里有个容易被忽略的细节AUTH命令本身是允许在未认证状态下发送的否则就成了死锁——你不认证不让发命令但不发命令又没法认证。所以 Redis 的设计是未认证时只放行AUTH以及少数几个如HELLO、QUIT、RESET之类的命令其余一律拦截。我在实际排查中总结出一个规律这个报错出现的场景90% 集中在下面几类。新搭的环境配置文件里加了requirepass但客户端连接代码没同步加密码。老环境本来没密码运维做安全加固时统一加了密码但漏改了某个服务的配置。本地开发用的 Redis 和测试/生产用的配置不一致代码在本地跑得好好的一上测试环境就炸。用可视化客户端比如 Another Redis Desktop Manager、Redis Desktop Manager 这类工具连的时候连接配置里密码那一栏空着。主从或者集群环境下只给主节点配了密码从节点或者哨兵没配导致切换后认证失败。所以看到这个报错先别急着怀疑 Redis 服务本身八成是密码这两个字在作怪。下面我会把认证机制、配置方式、各种客户端的处理办法、以及排查思路一层层拆开讲尽量让不管你是刚接触 Redis 的新手还是已经用了几年但一直没深究认证机制的老手都能从中拿到能直接用的东西。2. Redis 认证机制与 requirepass 配置全解析2.1 requirepass 是怎么生效的Redis 的认证开关就是配置文件里的requirepass这一行。默认情况下它是被注释掉的也就是没有密码。一旦你把它打开并设了值比如requirepass YourStrongPassword123服务端启动后就会要求所有连接先认证。这里有个很多人不知道的点requirepass设置的是默认用户的密码。Redis 6.0 引入了 ACL访问控制列表之后认证体系变得更复杂了requirepass实际上等价于给默认用户default设置密码。在 6.0 之前只有这一种密码机制6.0 之后你可以用 ACL 给不同用户配不同密码和权限但requirepass依然兼容保留。这就解释了一个常见困惑为什么我在配置文件里明明写了requirepass用CONFIG GET requirepass却能看到值但客户端还是报 NOAUTH因为配置文件改了之后如果没有重启 Redis 或者没有用CONFIG SET动态生效改动是不起作用的。反过来如果你用CONFIG SET requirepass newpass动态改了密码这个改动在重启后会丢失除非你同时写回配置文件。我建议的做法是生产环境统一走配置文件 重启或滚动重启临时调试才用CONFIG SET。因为动态改密码这种操作一旦忘了写回配置下次重启就会出现密码莫名其妙变回去了的灵异事件。2.2 认证命令的几种写法认证的核心命令就一个AUTH但写法有讲究。老版本6.0 之前只支持单参数AUTH YourStrongPassword1236.0 之后支持双参数指定用户名AUTH default YourStrongPassword123如果你用的是 ACL 体系下的自定义用户就得用双参数形式比如AUTH myuser mypassword。单参数形式在 6.0 里默认认证的是default用户所以如果你把默认用户禁用了、只留了自定义用户单参数AUTH就会失败。这里插一句实操经验很多客户端库在底层封装AUTH的时候用的是单参数形式。如果你在服务端把default用户删了或者设了nopass之外的奇怪配置客户端就可能认证不上。所以除非你有明确的 ACL 需求否则保持default用户可用、用requirepass设密码是最省心的方案。2.3 密码强度与配置的取舍有人会问密码设多复杂合适我的经验是内网环境也别用空密码或者123456这种。Redis 未授权访问是历史上被利用最多的漏洞之一攻击者拿到未授权访问后可以写文件、写计划任务后果很严重。所以哪怕是在内网也建议设一个足够长的随机密码。但密码也不是越长越好因为有些客户端或者中间件对密码长度有限制而且太长的密码在配置文件里明文存放也不安全。折中方案是用 32 位左右的随机字符串通过环境变量或者配置中心注入而不是硬编码在代码里。另外Redis 6.0 支持在配置文件里用 ACL 文件管理用户可以把密码单独放在一个权限更严格的文件里主配置文件只引用。这个做法在合规要求高的场景下很实用。3. 不同客户端与场景下的认证实操3.1 redis-cli 命令行认证最直接的方式就是在redis-cli里敲AUTHredis-cli 127.0.0.1:6379 AUTH YourStrongPassword123 OK 127.0.0.1:6379 GET somekey somevalue但每次都手动敲太麻烦redis-cli提供了两个便捷参数# 方式一-a 参数直接带密码 redis-cli -h 127.0.0.1 -p 6379 -a YourStrongPassword123 # 方式二连接后自动认证推荐避免密码出现在命令历史里 redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379 AUTH YourStrongPassword123注意用-a参数时密码会出现在 shell 历史记录和进程列表里存在泄露风险。生产环境建议用AUTH交互式输入或者用REDISCLI_AUTH环境变量。REDISCLI_AUTH这个环境变量是很多人不知道的实用技巧export REDISCLI_AUTHYourStrongPassword123 redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379 PING PONG这样密码不会出现在命令行参数里相对安全一些。不过环境变量本身也可能被同机器的其他进程读到所以最稳妥的还是交互式AUTH。3.2 可视化客户端配置用 Another Redis Desktop Manager、Redis Desktop Manager 这类可视化工具时NOAUTH 报错几乎都是因为连接配置里密码栏没填。以 Another Redis Desktop Manager 为例新建连接的时候有个Auth或者密码输入框把requirepass的值填进去就行。这里有个坑有些旧版本的 Redis Desktop Manager 对 Redis 6.0 的 ACL 支持不好如果你用的是自定义用户而不是默认用户可能需要在用户名栏也填上。如果只填密码认证不上试试把用户名填成default。还有一个更隐蔽的坑可视化工具通常会保存连接配置如果你之前连的是没密码的实例后来服务端加了密码工具里保存的旧配置不会自动更新还是会报 NOAUTH。这时候需要编辑连接把密码补上。3.3 各语言客户端配置示例不同语言的 Redis 客户端配置密码的方式大同小异但细节上有差异。下面列几个常见的。JavaJedisJedisPoolConfig poolConfig new JedisPoolConfig(); JedisPool jedisPool new JedisPool(poolConfig, 127.0.0.1, 6379, 2000, YourStrongPassword123);注意 Jedis 的构造函数里密码参数的位置。老版本和新版本参数顺序可能不同用之前确认一下版本对应的 API。JavaLettuceRedisClient client RedisClient.create(redis://:YourStrongPassword123127.0.0.1:6379);Lettuce 用的是 URI 形式密码放在:和之间。如果密码里有特殊字符比如、:、/需要做 URL 编码否则会解析错误。这个坑我踩过密码里带个结果连不上排查了半天。Pythonredis-pyimport redis r redis.Redis(host127.0.0.1, port6379, passwordYourStrongPassword123)redis-py 的password参数直接传就行。如果是 6.0 的自定义用户还可以传username参数。Node.jsioredisconst Redis require(ioredis); const redis new Redis({ host: 127.0.0.1, port: 6379, password: YourStrongPassword123 });Spring Bootapplication.ymlspring: redis: host: 127.0.0.1 port: 6379 password: YourStrongPassword123Spring Boot 的配置最省事但要注意如果你用的是 Redis 集群或者哨兵模式密码配置的位置不一样。集群模式下要在spring.redis.cluster下配哨兵模式在spring.redis.sentinel下配。配错位置的话启动不报错但运行时报 NOAUTH。3.4 主从、哨兵、集群场景的认证这是 NOAUTH 报错的高发区。主从复制的时候从节点需要连主节点同步数据如果主节点有密码而从节点没配从节点就会报 NOAUTH复制中断。主从场景下从节点的配置文件里需要加masterauth YourStrongPassword123 requirepass YourStrongPassword123masterauth是从节点连主节点用的密码requirepass是从节点自己对外提供的密码。两个都要配缺一不可。很多人只配了requirepass忘了masterauth结果从节点一直连不上主节点。哨兵模式下更复杂哨兵本身要连 Redis 实例还要在故障切换后通知其他节点。哨兵的配置文件里需要sentinel auth-pass mymaster YourStrongPassword123集群模式下每个节点都要配requirepass和masterauth而且所有节点的密码必须一致否则节点之间通信会失败。提示主从/哨兵/集群场景下改密码是个高危操作。因为要同时改多个节点改的过程中如果顺序不对会导致复制中断或者切换失败。建议的做法是先改从节点再改主节点最后改哨兵或者用滚动方式逐个改每改一个确认状态正常再改下一个。4. 排查思路与常见问题速查4.1 一套可复用的排查流程遇到 NOAUTH我一般按下面的顺序排查基本能在几分钟内定位。第一步确认服务端到底有没有设密码redis-cli -h 127.0.0.1 -p 6379 127.0.0.1:6379 CONFIG GET requirepass 1) requirepass 2) YourStrongPassword123如果返回空字符串说明服务端没设密码那 NOAUTH 就不是密码问题可能是 ACL 配置的问题需要查ACL LIST。如果返回了密码值说明服务端确实要求认证。第二步确认客户端有没有带密码。这个要看具体客户端的配置检查连接参数里password或者auth相关的字段。第三步确认密码是否一致。有时候服务端密码改了客户端还是旧的就会报 NOAUTH。这种情况在密码轮换的时候特别常见。第四步如果是主从/集群确认所有节点的密码配置是否一致masterauth有没有配。4.2 常见问题速查表现象可能原因排查方法解决方式redis-cli 连上后执行命令报 NOAUTH服务端设了密码客户端没认证CONFIG GET requirepass看是否有值执行AUTH或连接时带密码代码在本地正常测试环境报 NOAUTH环境配置不一致对比两边 Redis 配置同步密码配置可视化工具连不上报 NOAUTH连接配置密码栏为空检查工具连接配置补填密码主从复制中断报 NOAUTH从节点没配 masterauth查从节点日志补配 masterauth哨兵切换后报 NOAUTH哨兵没配 auth-pass查哨兵配置补配 sentinel auth-pass密码改了之后部分服务报 NOAUTH密码轮换不彻底逐个检查服务配置统一更新密码用 ACL 自定义用户报 NOAUTH单参数 AUTH 认证的是 default 用户查 ACL 配置用双参数 AUTH 或恢复 default 用户4.3 几个容易踩的坑坑一密码里有特殊字符。如果密码包含、:、/、#这些字符在 URI 形式的连接串里需要 URL 编码在配置文件里可能需要引号包裹。我遇到过密码里带#导致配置文件把后面内容当注释的情况排查了很久。坑二CONFIG SET requirepass之后忘了写回配置文件。动态改密码很方便但重启就丢。建议改完立刻CONFIG REWRITE写回配置文件或者手动改配置文件后重启。坑三只改了主节点密码忘了从节点。主从环境下主节点密码改了从节点的masterauth没改复制立刻中断。这种问题在监控上表现为从节点延迟飙升或者复制状态异常。坑四客户端连接池里的旧连接。有些客户端用了连接池密码改了之后池子里的旧连接还是用旧密码认证的会持续报 NOAUTH。这时候需要重启客户端服务让连接池重建。坑五Docker 环境下的配置挂载。用 Docker 跑 Redis 的时候如果配置文件是通过 volume 挂载的改了宿主机的配置文件容器里的配置不会自动生效需要重启容器。而且要注意挂载路径是否正确有时候挂载错了容器用的是默认配置无密码但你以为用的是有密码的配置。5. 认证之外Redis 安全加固的延伸思考NOAUTH 这个报错表面上看是个配置问题但往深了想它其实暴露的是 Redis 安全配置的完整性问题。我见过太多环境Redis 是裸奔的——没有密码、绑定在0.0.0.0、端口对公网开放。这种情况下NOAUTH 反而不会出现因为根本没开认证但风险比报错大得多。所以借着这个话题我想延伸聊几句 Redis 安全加固的实操建议。第一绑定地址。默认配置里bind 127.0.0.1是注释掉的意味着监听所有网卡。生产环境应该明确绑定内网 IP不要监听0.0.0.0。第二保护模式。Redis 有个protected-mode配置默认是yes。在保护模式下如果没有设密码且没有绑定特定地址Redis 只接受本机连接。这个机制是为了防止裸奔的 Redis 被外部访问。但很多人为了图方便把它设成no这就把最后一道防线也撤了。第三重命名危险命令。FLUSHALL、FLUSHDB、KEYS、CONFIG这些命令在生产环境应该重命名或者禁用防止误操作或者被恶意利用。可以在配置文件里用rename-command实现。第四ACL 精细化权限。Redis 6.0 的 ACL 可以给不同应用分配不同用户每个用户只能访问特定的 key 前缀和命令。这样即使某个应用的密码泄露影响范围也可控。这个特性在微服务架构下特别有用。第五密码管理。密码不要硬编码在代码里用环境变量、配置中心或者密钥管理服务注入。密码要定期轮换轮换时注意前面提到的主从/集群同步问题。这些措施和 NOAUTH 报错的关系在于当你把安全加固做到位之后NOAUTH 这类报错反而会更频繁地出现因为认证环节变多了。这时候需要的不是把认证关掉而是把客户端的配置同步做好。我个人的做法是把 Redis 的连接配置统一收口到一个配置模块里所有服务从这个模块取配置改密码的时候只改一处避免遗漏。6. 我踩过的那些坑和最后的小技巧说几个我实际踩过的坑都是文档里不会写的。有一次帮一个团队排查 NOAUTH查了半天发现是他们的配置中心里 Redis 密码这一项被误删了客户端拿到空密码去认证服务端当然拒绝。这种问题在配置中心化的架构里特别隐蔽因为本地看代码没问题问题出在配置中心的数据上。还有一次是 Docker Compose 环境Redis 的配置文件挂载路径写错了容器实际用的是镜像里的默认配置无密码但应用配置里带了密码结果应用连上去认证失败——因为服务端根本没设密码你发AUTH它反而会报错老版本会报ERR Client sent AUTH, but no password is set。这个报错和 NOAUTH 是反过来的但根因都是配置不一致。最后分享一个小技巧在客户端连接 Redis 之后先执行一次PING来验证认证是否成功。因为PING在未认证状态下也会被拦截并返回 NOAUTH所以它能作为认证是否生效的快速探针。很多连接池的健康检查就是用PING实现的如果你看到健康检查日志里刷 NOAUTH那基本可以确定是认证配置的问题。另外如果你在用 Kubernetes 部署 Redis密码通常放在 Secret 里。改密码的时候要同时更新 Secret 和引用它的 Deployment而且要注意 Pod 重启的顺序。KubeSphere 这类平台上有可视化的 Secret 管理改起来方便但别忘了改完之后要触发相关 Pod 的重启否则旧 Pod 还是用旧密码。Redis 的认证机制本身不复杂复杂的是它在各种部署形态单机、主从、哨兵、集群、容器化下的配置组合。把requirepass、masterauth、sentinel auth-pass这几个配置项的关系理清楚再配合一套统一的配置管理流程NOAUTH 这类问题基本就能绝迹了。
