Authelia Redis 会话存储配置指南:从单实例到 Redis Sentinel 高可用
【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia
Authelia 默认使用进程内内存(in-memory)会话存储,这在单机部署下开箱即用,但在多副本、Kubernetes 等高可用场景中会因会话状态无法共享而失效。本文以 docs/content/configuration/session/redis.md 为主干,完整讲解session.redis配置块的全部参数(连接、认证、连接池、TLS、Sentinel 高可用),并结合 internal/session/provider_config.go、internal/configuration/schema/session.go 等源码与校验逻辑,帮助你从零搭建一个生产可用的 Redis 会话后端。读完本文,你将能独立完成单实例 Redis、TLS 加密连接以及 Redis Sentinel 故障转移三种场景的配置与排错。
为什么需要 Redis 会话存储
Authelia 依赖会话(Session)来判断用户是否已通过认证。默认情况下,会话数据保存在 Authelia 进程的内存中,这种方案:
- 无额外依赖,单机部署零配置即可运行;
- 是有状态(stateful)的——如果 Authelia 进程重启、崩溃或被调度器迁移到其他节点,内存中的会话会全部丢失,用户需要重新登录;
- 无法在多个 Authelia 副本间共享,因此不适用于高可用(HA)与 Kubernetes 部署。
官方在 会话存储总览文档 中明确指出:内存与 Redis 分别被称为stateful与stateless提供方,在 Kubernetes 或高可用场景下应优先选择无状态的 Redis。启用 Redis 后,任何副本都能读取同一个会话,单点故障不再导致全量登录失效,这也是官方强烈建议生产环境使用 Redis 的原因。
从源码角度看,会话提供方的选择发生在 NewSessionProvider:当配置了config.Redis时,会话序列化器被替换为EncryptingSerializer,存储提供方被替换为基于github.com/fasthttp/session/v2/providers/redis的 Redis 提供方;当HighAvailability.SentinelName非空时进一步使用redis.NewFailover(Sentinel 故障转移模式),否则使用redis.New直连模式。三者(内存、Redis、Redis Sentinel)在 会话总览文档 中被归纳为两类提供方,其中 Sentinel 可视为独立的第三个选择。
需要特别注意的是:一旦启用 Redis 会话存储,session.secret就成为强制项。校验器在 internal/configuration/validator/session.go 的validateRedisCommon中检查config.Secret为空即报错(session: redis: option 'secret' is required)。原因是会话数据写入 Redis 前会经过 AES-GCM 加密(详见后文“加密序列化器”一节),secret 正是加密密钥的派生来源。
完整配置示例
以下是一个覆盖全部可选能力的示例(部分参数按需使用,生产环境请结合自身环境调整):
session: secret: 'insecure_session_secret' # 必填:会话加密密钥,建议 64 位以上随机字母数字串 redis: host: '127.0.0.1' port: 6379 timeout: '5s' max_retries: 0 username: 'authelia' password: 'authelia' database_index: 0 maximum_active_connections: 8 minimum_idle_connections: 0 tls: server_name: 'myredis.example.com' skip_verify: false minimum_version: 'TLS1.2' maximum_version: 'TLS1.3' certificate_chain: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- private_key: | -----BEGIN PRIVATE KEY----- ... -----END PRIVATE KEY----- high_availability: sentinel_name: 'mysentinel' # 如果配置了 sentinel_username,Authelia 使用基于 ACL 的认证; # 否则使用传统的 requirepass 认证。 sentinel_username: 'sentinel_user' sentinel_password: 'sentinel_specific_pass' nodes: - host: 'sentinel-node1' port: 26379 - host: 'sentinel-node2' port: 26379 route_by_latency: false route_randomly: false其中host、high_availability.sentinel_name为必填项(Sentinel 场景下host与nodes至少提供其一),其余参数均有默认值。下面逐一展开每个选项的含义、默认值、约束与底层实现。
基础连接选项
host
| 类型 | 必填 | 默认值 |
|---|---|---|
| string | 是 | 无 |
Redis 服务器的主机名或 Unix Socket 路径。若使用 IPv6 字面地址,必须用方括号包裹并加引号:
host: '[fd00:1111:2222:3333::1]'校验逻辑(validateRedis)通过path.IsAbs判断 host 是否为绝对路径:若为绝对路径则视为 Unix Socket(此时端口不再生效,源码中network = "unix"、addr = config.Redis.Host),否则视为 TCP 主机名。这解释了为何文档强调“host 或 unix socket 路径”二选一。
port
| 类型 | 必填 | 默认值 |
|---|---|---|
| integer | 否 | 6379 |
Redis 监听端口。TCP 模式下端口必须落在 1~65535 区间,否则校验失败并报错option 'port' must be between 1 and 65535(错误常量定义)。当 host 是 Unix Socket 路径时,端口不再参与连接地址的拼接。
timeout
| 类型 | 必填 | 默认值 |
|---|---|---|
| string,integer(duration 语法) | 否 | 5 秒 |
Redis 连接超时时间,支持5s、1m等 Go duration 写法。默认值定义在 DefaultRedisConfiguration 中(Timeout: time.Second * 5)。在源码中它被映射为redis.Config.DialTimeout,即建立 TCP/TLS 连接的超时上限。
max_retries
| 类型 | 必填 | 默认值 |
|---|---|---|
| integer | 否 | 0 |
单条命令失败时的最大重试次数。文档明确说明设为 0 表示完全禁用重试。注意:虽然 jsonschema 描述中曾出现default=3,但实际默认值常量(schema/session.go)为0,与文档一致——请以 0 为准。在故障转移场景下,该值会原样传给redis.FailoverConfig.MaxRetries。
认证与数据隔离
username
| 类型 | 必填 | 默认值 |
|---|---|---|
| string | 否 | 无 |
Redis 6.0+ 的 ACL 认证用户名,对应 RedisAUTH命令的用户名参数。若你的 Redis 未配置 ACL,通常无需设置此值(Redis 仍兼容仅密码认证)。启用后,源码将其映射为redis.Config.Username,配合password完成 ACL 认证。
password
| 类型 | 必填 | 默认值 | 敏感项 |
|---|---|---|---|
| string | 否 | 无 | 是(secret) |
Redis 认证密码。官方强烈建议使用 64 位及以上长度的随机字母数字串,并同步修改 Redis 用户的实际密码。生成方式可参考 生成安全随机值指南 中的 “Generating a Random Alphanumeric String” 一节。
database_index
| 类型 | 必填 | 默认值 |
|---|---|---|
| integer | 否 | 0 |
Redis 数据库编号,语义等价于SELECT命令的参数。源码中对应redis.Config.DB。若你的 Redis 实例还承载其他业务数据,建议为 Authelia 分配独立 database_index 以便隔离。
连接池:并发与空闲连接
maximum_active_connections
| 类型 | 必填 | 默认值 |
|---|---|---|
| integer | 否 | 8 |
同一时刻允许打开到 Redis 的最大连接数。校验器在 validateRedis 中将其兜底为默认值 8(MaximumActiveConnections <= 0时重置),源码中映射为redis.Config.PoolSize。该值决定了 Authelia 并发请求 Redis 的能力上限,需要结合实例并发用户数调优:过小会导致请求排队,过大则会耗尽 Redis 的可用连接。
minimum_idle_connections
| 类型 | 必填 | 默认值 |
|---|---|---|
| integer | 否 | 0 |
保持空闲的最小连接数(上限受maximum_active_connections约束),映射为redis.Config.MinIdleConns。当 Redis 建连延迟较高(如跨机房、TLS 握手开销大)时,维持空闲连接可以避免每次请求都经历完整的建连过程,从而降低延迟。
另外,无论是否配置该选项,源码都会设置ConnMaxIdleTime: 300(秒),即空闲连接最长闲置 5 分钟后被回收,避免连接被 Redis 服务端超时断开后仍被复用。
TLS 加密连接
tls
| 类型 | 必填 | 默认值 |
|---|---|---|
| structure(TLS) | 否 | 无 |
定义该项即启用 TLS 套接字连接,并控制对 Redis 服务的 TLS 证书校验参数。默认情况下,Authelia 使用系统证书信任库校验 TLS 证书;全局选项certificates_directory(见 杂项配置介绍)可用于扩充信任的 CA 证书。
TLS 子结构包含以下字段:
| 字段 | 说明 |
|---|---|
server_name | TLS SNI 与证书校验使用的服务器名,默认取自redis.host |
skip_verify | 设为true跳过证书校验(生产环境不建议) |
minimum_version | 最低 TLS 版本,默认TLS1.2(DefaultRedisConfiguration) |
maximum_version | 最高 TLS 版本,如TLS1.3 |
certificate_chain | 客户端证书链(PEM 格式),用于双向 TLS(mTLS) |
private_key | 与certificate_chain配套的私钥(PEM 格式) |
在校验器validateRedisCommon(internal/configuration/validator/session.go)中,TLS 默认配置的ServerName会取config.Redis.Host、最低版本取 TLS1.2,随后调用ValidateTLSConfig进行合法性校验。运行时,NewSessionProvider 通过utils.NewTLSConfig(config.Redis.TLS, certPool)将配置转换为*tls.Config,再注入 Redis 提供方。
Redis Sentinel 高可用
high_availability
定义本结构即启用 Redis Sentinel 连接模式。从源码看,判断依据是HighAvailability != nil && SentinelName != ""(provider_config.go),此时提供方名称变为redis-sentinel,使用redis.NewFailover创建故障转移客户端。官方文档也提及未来可能支持 Redis Cluster(redis cluster),当前版本仅提供 Sentinel 支持。
Sentinel 模式下,host与port的含义发生变化:host必须是Sentinel 主机而非普通 Redis 主机;实际的 Redis 主从地址由 Sentinel 通过内部命令动态确定。连接地址列表的组装逻辑见 provider_config.go:先加入host:port,再追加nodes中每一项(自动去重),全部用于初始化 Sentinel 客户端。
sentinel_name
| 类型 | 必填 | 默认值 |
|---|---|---|
| string | 是 | 无 |
Sentinel 的 master 名称。它是在 Sentinel 配置中定义的逻辑名称,不是主机名。当前版本的高可用配置必须定义此项,校验器缺失时报option 'sentinel_name' is required(const.go)。
sentinel_username
| 类型 | 必填 | 默认值 |
|---|---|---|
| string | 否 | 无 |
Sentinel 连接的用户名。若提供,则与sentinel_password一起对 Sentinel 使用ACL 认证;若只提供密码,则使用传统requirepass认证。对应redis.FailoverConfig.SentinelUsername。
sentinel_password
| 类型 | 必填 | 默认值 | 敏感项 |
|---|---|---|---|
| string | 视情况(提供sentinel_username时必须) | 无 | 是(secret) |
Sentinel 连接密码。与sentinel_username配合时为 ACL 认证,单独使用时为 requirepass 认证。同样强烈建议使用 64 位以上随机字母数字串(生成方法同上文password一节)。对应redis.FailoverConfig.SentinelPassword。
nodes
Sentinel 节点列表,用于负载均衡。该列表会与上层的host合并(provider_config.go),因此你既可以通过顶层host指定一个 Sentinel 地址,也可以(或同时)通过nodes声明多个。host与nodes至少配置其一,否则校验报option 'host' or the 'high_availability' option 'nodes' is required。每个节点包含:
- host: redis-sentinel-0 port: 26379host
| 类型 | 必填 | 默认值 |
|---|---|---|
| string | 是(每个节点) | 无 |
该 Sentinel 节点的地址。若任一节点缺失 host,校验报错option 'host' is required for each node...(validator/session.go)。
port
| 类型 | 必填 | 默认值 |
|---|---|---|
| integer | 否 | 26379 |
该 Sentinel 节点的端口,未配置时自动填充默认值 26379。
route_by_latency
| 类型 | 必填 | 默认值 |
|---|---|---|
| boolean | 否 | false |
设为true时优先选择低延迟的 Sentinel 节点。对应redis.FailoverConfig.RouteByLatency。
route_randomly
| 类型 | 必填 | 默认值 |
|---|---|---|
| boolean | 否 | false |
设为true时随机选择 Sentinel 节点。对应redis.FailoverConfig.RouteRandomly。两个路由选项都默认为关闭,可按需启用其一。
校验规则速查
结合 internal/configuration/validator/session.go 与 const.go,Redis 相关配置的校验要点汇总如下:
| 校验项 | 规则 | 报错信息 |
|---|---|---|
session.secret | Redis 模式下必填 | session: redis: option 'secret' is required |
host | 直连模式下必填 | option 'host' is required |
host或nodes | Sentinel 模式至少其一 | option 'host' or the 'high_availability' option 'nodes' is required |
port | TCP 模式必须为 1~65535;Unix Socket 模式忽略 | option 'port' must be between 1 and 65535 |
sentinel_name | 高可用模式必填 | option 'sentinel_name' is required |
nodes[].host | 每个节点必填 | option 'host' is required for each node... |
nodes[].port | 缺省自动补 26379 | — |
maximum_active_connections | 小于等于 0 时重置为 8 | — |
这些规则在 session_test.go 中均有对应测试用例覆盖,例如非法端口上下界(-1 与 65536)、缺失 secret、Sentinel 节点缺 host、host 与 nodes 同时为空等场景。
会话加密与无状态原理
启用 Redis 后,会话数据在落盘前会被 EncryptingSerializer 加密。其工作流程为:
- 用
session.secret通过utils.DeriveLegacyCryptographicKey派生 256 位密钥; - 编码阶段(
Encode):先将会话字典 msgpack 序列化(MarshalMsg),再使用AES-GCM加密(utils.Encrypt); - 解码阶段(
Decode):先解密再反序列化,恢复会话字典。
这正是“无状态”的关键:Redis 中保存的是加密后的会话载荷,任何 Authelia 副本只要持有相同的session.secret就能解密,从而实现多副本共享会话而不依赖进程内状态。这也再次印证了为什么session.secret必须妥善保管并保持所有副本一致。
关于“无状态 vs 有状态”的架构意义,可进一步阅读 无状态架构说明;会话密钥的生成建议见 生成安全随机值指南。
生产部署建议
结合文档与源码实现,给出以下实操建议:
- 生产环境务必启用 Redis:即使当前是单实例,也应提前规划,避免后期迁移时用户重新登录;Kubernetes/HA 场景则必须使用 Redis(推荐 Sentinel 模式)。
- 使用强随机 secret:所有副本的
session.secret必须一致,长度建议 64 位以上随机字母数字串,否则会话加密形同虚设。 - 认证密码同样使用强随机值:
password与sentinel_password建议 64 位以上,并同步更新 Redis 用户密码。 - 尽量启用 TLS:Redis 会话载荷虽已加密,但传输链路仍建议启用 TLS(配置
tls块),并使用certificates_directory或系统信任库完成证书校验;skip_verify仅用于测试。 - 连接池按需调优:根据并发请求量调整
maximum_active_connections;跨网络或有 TLS 开销时提高minimum_idle_connections降低建连延迟。 - Sentinel 高可用:至少配置两个 Sentinel 节点,
sentinel_name必须与 Sentinel 配置中的 master 名一致;host与nodes至少提供一个 Sentinel 地址。
通过本文的配置示例、参数速查与源码佐证,你可以根据自身架构在“单实例 Redis”与“Redis Sentinel 高可用”之间做出选择,并完成一套安全、可维护的 Authelia 会话后端配置。
【免费下载链接】autheliaThe Single Sign-On Multi-Factor portal for web apps. OpenID Certified™ and Post-Quantum Cryptography Ready.项目地址: https://gitcode.com/GitHub_Trending/au/authelia
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考