ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

游戏登录鉴权整体架构

游戏登录鉴权整体架构 先明确一件事登录鉴权的本质不是验证密码而是在不可信的客户端和有状态的游戏服务器之间建立一条可验证、可撤销、防伪造的信任链。整个架构都是围绕这条信任链的建立、传递和失效来设计的。所以这篇从信任是怎么一步步传递的讲起而不是罗列几个服务。一、先看清核心矛盾游戏登录比普通 Web 登录难难在三点1. 游戏服是长连接、有状态的Web 每个请求都能带 token 重新验证游戏服是一条 TCP/UDP 长连接维持几小时。这条连接一旦建立中途怎么验证身份怎么踢人2. 有多个异构服务器登录服、大厅服、网关、战斗服……玩家要在它们之间跳转信任必须能跨服务器传递不能每跳一个服务就让玩家重新输密码。3. 客户端完全不可信外挂、破解、盗号。任何客户端说自己是谁都不能信必须有服务端签发的、不可伪造的凭证。架构的所有设计都是在解这三个问题。二、信任链的三个阶段我把整个流程拆成三段每一段解决一个不同的问题阶段一身份认证 阶段二会话建立 阶段三连接鉴权 「你是不是你」 「换一张游戏门票」 「凭票进入游戏服」 │ │ │ 账号服(Auth) 登录服(Login) 网关/游戏服(Gateway) │ │ │ 验证密码/第三方 签发 Session Token 校验票据建立长连接 ▼ ▼ ▼ 返回 Auth Token 返回可跳转的门票 维持有状态会话关键洞察长期凭证账号密码只在最开始用一次之后全程用短期的、专用的凭证。这样即使某个环节泄漏损失可控、可撤销。三、阶段一身份认证账号服职责单一确认这个人拥有这个账号然后签发一个 Auth Token。之后账号服就退场了不参与游戏流程。支持多种认证来源但收敛到同一个出口账号密码 ──┐ 微信/QQ ──┤ Apple/Google ─┤── 账号服统一验证 ── 签发 Auth Token (JWT) 手机验证码 ──┤ 含 userId、过期时间、签名 游客登录 ──┘设计要点第三方登录OAuth客户端拿第三方 code由服务端去换第三方的用户信息绝不让客户端直接传我是某某用户。密码存储bcrypt/argon2加盐哈希永不明文永不可逆。Auth Token 用 JWT无状态下游服务用公钥验签就能确认真伪不用回账号服查询。但 JWT 有个致命问题——签发后无法主动作废所以它必须短命如 5 分钟只用来换下一阶段的门票。四、阶段二会话建立登录服拿着 Auth Token 来换一张真正用于游戏的门票Session Token。为什么要换因为 JWT 作废不了而游戏需要能随时踢人、能限制单点登录、能记录在线状态。这些都需要有状态的会话存在 Redis 里。客户端 ──Auth Token── 登录服 │ 1. 验证 Auth Token 签名 2. 处理顶号逻辑下面详说 3. 生成 Session写入 Redis key: session:{userId} value: { token, serverId, loginTime, ... } 4. 分配要去哪个大厅/区服 │ 客户端 ──Session Token 目标服地址──┘踩坑重点——单点登录 / 顶号同一账号重复登录是游戏最常见的场景切设备、掉线重连、盗号者同时登录。策略在 Redis 里实现新登录到来 查 session:{userId} 是否已存在 ├── 存在 → 向旧会话所在的游戏服发踢人通知 │ 覆盖为新 Session └── 不存在 → 直接写入 // 这样保证一个账号全局只有一个有效 Session // 旧客户端下次心跳/操作时Session 已失效被强制下线Session Token 通常是随机字符串不是 JWT因为它需要能被主动删除来实现踢人——删掉 Redis 里的 key这个 token 立刻失效。这正好补上了 JWT 的短板。五、阶段三连接鉴权网关 / 游戏服客户端带着 Session Token 去连游戏网关建立长连接。客户端 ──建立TCP/WS连接── 网关 └── 首包携带 Session Token │ 网关拿 token 查 Redis ├── 有效 → 绑定 connection ↔ userId │ 之后这条连接上的所有包 │ 都默认已鉴权 └── 无效 → 断开连接这里是有状态长连接如何鉴权的答案鉴权只在握手时做一次。验证通过后网关在内存里维护一张连接 → userId的映射表。此后这条连接上的每个游戏协议包天然就是这个玩家发的不需要每包都验 token。这也带来两个必须处理的问题1. 如何中途踢人 / 使会话失效连接建立后 token 就不再检查了怎么踢—— 由服务端主动关闭连接。运营封号、顶号、Session 过期都是服务端找到那条 connection 直接 close而不是等客户端来验证。2. 断线重连长连接必然会断网络抖动、切后台。设计上 Session 的生命周期要比连接长连接断了Redis 里的 Session 保留一小段时间如 3 分钟。客户端用同一个 Session Token 重连能直接恢复不用重走登录。超时未回来才真正清理。六、多服务器间的信任传递玩家从大厅进入战斗服怎么让战斗服相信他两种主流做法方案 A共享 Session 存储推荐所有服务器都能访问同一个 Redis。玩家跳转时带着 Session Token新服务器自己查 Redis 验证。简单、一致。方案 B服务端签发跳转票据大厅服签一个短命的、绑定了目标战斗服 userId 过期时间的一次性 ticket。战斗服验签 检查一次性用完即焚防重放。适合服务器不共享存储、或跨物理区域的场景。大厅服 ──签发一次性ticket── 客户端 ──ticket── 战斗服 │ 验签 检查未使用过 检查 targetServer 自己 │ 标记ticket已用(Redis)七、整体架构图┌──────────────┐ │ 客户端 │ └──────┬───────┘ ①账号密码/第三方 │ ③Session Token ┌─────────────┼──────────────┐ ▼ │ ▼ ┌──────────────┐ │ ┌──────────────┐ │ 账号服Auth │ │ │ 游戏网关GW │ │ 验证身份 │ │ │ 长连接鉴权 │ │ 签发AuthToken │ │ │ 连接↔user映射 │ └──────┬───────┘ │ └──────┬───────┘ │ │ │ │②AuthToken换票 ▼ │ │ ┌──────────────┐ │ └─────│ 登录服Login │ │ │ 验票/签Session│ │ │ 处理顶号/分服 │ │ └──────┬───────┘ │ │ │ ┌──────▼──────────────▼──────┐ │ Redis (Session存储) │ │ session:{userId} → {...} │ │ 单点登录/踢人/断线重连的真相源 │ └─────────────────────────────┘ │ ┌──────▼───────┐ │ 持久层 MySQL │ │ 账号/密码哈希 │ └──────────────┘八、安全设计清单信任链的每个环节都可能被攻击逐个堵威胁对策传输被窃听/篡改全链路 TLS登录用 HTTPS长连接用 WSS/自研加密Token 被盗用短过期 可撤销Session 存 Redis 可删 绑定设备指纹重放攻击一次性 ticket、请求带 nonce 时间戳撞库/爆破登录失败次数限制、验证码、异地登录风控盗号单点登录顶号、登录通知、二次验证客户端伪造身份一切以服务端签发/存储的凭证为准客户端说的都不信DDoS 登录接口网关限流、账号服与游戏服物理隔离九、把整条链串起来的一句话总结长期密码只用一次换来短命 Auth Token无状态、验真伪→ Auth Token 换来可撤销的 Session有状态、能踢人→ Session 在握手时把长连接和玩家身份绑定一次 → 之后靠连接映射和服务端主动关连接来维持和撤销信任 → 跨服跳转靠共享 Session 或一次性票据传递信任。核心思想始终是信任逐级传递、凭证逐级变短命、状态集中在 Redis 作为唯一真相源、客户端永远不被信任。
返回列表