5.注册登录系列总结

5.总结


5.1 知识点

系列按「架构演变 → 票据技术 → 注册 → 登录」铺开:先看单机到分布式再到网关自验证的路线,再学 JWT 与 RSA 在 .NET 里怎么落地,最后两篇把鉴权服里的注册、登录与 Gate 上的验票、会话、顶号串成完整链路。


5.2 核心要点速览

架构角色与三阶段演变

链路上三类进程的职责:

角色 职责摘要 和「按用户名选鉴权」的关系
鉴权服 注册、校验密码、签发 JWT;多机时同一用户名固定落到同一台处理 这一层做「哈希取模 + position」
Gate 验 JWT、会话与进游戏前逻辑;顶号、延迟断线、GameAccount 缓存 验签在本进程完成
反向代理 / SLB 入口流量分拆 不替代「用户名 → 某台鉴权」的路由

演变对照(中央越答越少,边缘验票越多):

维度 早期 中期 现在常见
验证靠什么 中心库 + 与白名单/游戏服同步 鉴权集群 + 共享缓存里的 Token JWT 声明 + 各 Gate 公钥验签
扩展与故障面 单点易堵 缓存仍是热点,同步与一致性要设计 横向扩 Gate 相对顺;吊销、过期需单独立项
常见技术词 单体 / 中心鉴权 分布式鉴权 + Redis 等 JWT、OAuth2、微服务网关

早期示意是登录成功后往游戏服同步白名单;中期是缓存优先;本系列后半是鉴权签票、Gate 只信签名与声明。

JWT、RSA 与 .NET 侧用法

形态与算法

  • 传输形态:Header.Payload.Signature,前两段是 Base64Url,可解码查看,不是保密字段
  • HS256:同一 secret 签与验,实现快;任一验签方泄密即可造假票,多机分发 secret 要慎。
  • RS256:签发侧私钥、验证侧公钥,与「一台鉴权、多台 Gate」常见部署更合拍。

文中类分工

类型 角色 易踩坑
JwtPayload 装标准/自定义 claims expValidateLifetime 要一致
JwtSecurityToken issuer、audience、过期、SigningCredentials 演示可用 signingCredentials: null,上线不行
JwtSecurityTokenHandler WriteTokenValidateTokenReadJwtToken 异常类型按业务捕获,别一把吞

对称:SymmetricSecurityKey + SigningCredentials + HmacSha256;RSA:RsaSecurityKey + RsaSha256

验证参数

TokenValidationParameters 中与系列代码最相关:ValidateIssuerValidateAudienceValidateLifetimeValidateIssuerSigningKey,以及 ValidIssuer / ValidAudience / IssuerSigningKey。正文示例会关 ValidateLifetime线上打开并配合短时效或刷新,否则被盗令牌在过期前都可重放。

密钥格式

格式 与 C# 导出
PKCS#1 ExportRSAPublicKey / ExportRSAPrivateKey,结构直接
PKCS#8 ExportSubjectPublicKeyInfo / ExportPkcs8PrivateKey,可加密保护私钥

模长至少 2048;大载荷不宜直接 RSA 加密,签名更合适;数据加密填充宜 OAEP。

签发骨架(对齐正文写法)

var token = new JwtSecurityToken(
    issuer: "Tao",
    audience: "Tao",
    claims: jwtPayload.Claims,
    expires: DateTime.UtcNow.AddHours(1),
    signingCredentials: signingCredentials
);
return new JwtSecurityTokenHandler().WriteToken(token);

注册:选机、限流、同服准入、并发与缓存

客户端使用 AuthenticationSelectComponentMurmurHash3(userName) % AuthenticationList.Count 选地址。鉴权节点列表需与服务端配置同源或可热更,否则会出现整批错误路由。

鉴权启动时 AuthenticationComponent.UpdatePosition:读全量鉴权节点配置,得到本机 PositionAuthenticationCount

注册请求过场(顺序即防线顺序):

环节 作用
session.CheckInterval 限频
session.SetTimeout 会话生命周期
非空校验 用户名 / 密码
MurmurHash3(username) % AuthenticationCountPosition 非本 shard 则拒绝

同一用户名注册须串行:CoroutineLockComponent + AuthenticationRegisterLock,锁键 username.GetHashCode。内核:注册缓存 → 未命中再查库 → 新建 Account → 写缓存与超时;缓存命中视为已存在。文后虽建议密码加盐哈希,示例或为明文比对,仅用于跟流程

登录:鉴权发票、客户端拆票、Gate 验票与会话

登录错误码(与注释一致):0 成功;1 参数;2 无账号或密码错;3 非本机 shard。注册示例同样用数字码区分布合法 / 已存在 / 频控或错机,跨接口复用数码时最好落到枚举或文档,避免排障时对不上语义

登录在 AuthenticationLoginLock 内用 userName + password 作缓存键;命中则直接返回账号 id;否则查库、比对、更新 LoginTime、保存,再挂登录缓存(文中约 5s)。成功后 accountId 对 Gate 列表取模,JWT 中写入 aIdAddressSceneId

JWTParseComponent 只做分段与 Base64 填充解码,不验签;只为取 Address。Gate 用公钥 ValidateToken,且 GateJWTHelper 要求载荷里 SceneIdscene.SceneConfigId 一致,避免错接入口。

Account 在鉴权库;GameAccount 在 Gate 侧(含 SessionRunTimeId),可首次进 Gate 创建。GameAccountManageComponent 做进程内缓存,服务顶号与重连。

顶号与重连:

  • 登录成功挂 GameAccountFlagComponent;更新 SessionRunTimeId
  • 缓存已有账号则 CancelTimeoutsession.RunTimeId == account.SessionRunTimeId 视为重复点击,可直接返回。
  • 否则用旧 SessionRunTimeId 找旧 Session:先清空旧 flag,再通知重复登录、延迟断旧连,避免旧 Session 销毁误伤新连接。
  • 销毁路径:Disconnect 查缓存、CancelTimeout、落库、Remove

实现顺序建议

  1. 单进程跑通注册 → 登录 → 带 Gate 地址的 JWT,再拆多鉴权与 UpdatePosition
  2. 控制台先调通 RSA 签发 + 公钥 ValidateToken,再挂进 Gate RPC。
  3. 再补限频、position 双检、两把协程锁,最后做 Gate 缓存与顶号。

5.3 面试题精选

基础题

1. 登录流程里错误码 0/1/2/3 各表示什么?和「数字复用」有关的坑是什么?

题目

鉴权返回里 123 在本系列登录实现中分别对应哪些情况?注册侧也用数字码时,工程上要注意什么?

深入解析
  • 登录 Login 注释:0 成功;1 用户名或密码为空;2 账号不存在或密码不匹配;3 按用户名算出的 shard 不是当前鉴权机,应换机再试。
  • 注册侧示例里同样用较小整数表示参数错误、已存在、频控或错机等,若与登录共用一套数字而没有枚举或文档,日志与客户端提示很容易张冠李戴
  • 进阶排障:服务器列表变更后,大量 3 往往是客户端与服侧 AuthenticationCount / 节点顺序不一致,而不是用户密码真错了。
答题示例

这篇里登录:0 成功,1 参数不全,2 账号或密码不对,3 这台鉴权不该处理这个用户,要按哈希去别台。
注册也会返回 1、2、3 一类码,若和登录混用同一套数字,最好用枚举或协议文档写死含义,否则运营和客户端会对不上;成片 3 还要怀疑选机和服配置是否同源。

参考文章
  • 3.注册流程
  • 4.登录流程

进阶题

2. 客户端用 MurmurHash3 选鉴权机,服务端为什么还要用同一公式再算 position?

题目

只信客户端选路,或只在服务端校验,行不行?

深入解析
  • 客户端取模:把不同用户名的连接均匀散到多机,减轻单机,属于入口侧负载均衡。
  • 服务端用 MurmurHash3(username) % AuthenticationCount 与本地 Position 对齐:不信任客户端;配错地址、被篡改、列表不同步时,在后端直接拒绝,避免写错分片或脏数据。
  • 两边必须用同一哈希实现、同一有序节点列表;列表变更要同步配置中心或热更客户端,否则会出现「连上了但一直被 3 拒绝」。
答题示例

客户端哈希是为了分流;服务端再算一遍是为了防伪造路由和配错机,保证只有负责这个用户的那台鉴权能落库。
公式和机器列表必须严格一致,否则用户会觉得密码对也一直失败,其实是 shard 算错了。

参考文章
  • 3.注册流程
  • 4.登录流程

深度题

3. 客户端只解码 JWT Payload、Gate 才验签,和 SceneId 校验一起解决了什么问题?还有哪些残留风险?

题目

这种分工算不算「信任客户端带的地址」?SceneIdSceneConfigId 对不上为什么要拒绝?

深入解析
  • 客户端解码只为拿 Address 建连;是否允许进服由 Gate 验签决定,不是由客户端解析结果决定。若业务代码把未验签载荷当权限来源,属于实现错误。
  • SceneId 与当前 Gate 配置一致,才能防止拿着给 A 入口签的票去连 B 入口(票仍合法,但连错服)。
  • 残留风险:载荷可被任何人读取,不要塞隐私;示例未验过期,线上须打开 ValidateLifetime 或等价机制;令牌被盗后可在有效期内重放,需 HTTPS、短时效、刷新或踢人策略;登录缓存键若含明文密码,本身也是敏感面,应用安全存储与传输替代设计。
答题示例

客户端只解析 Payload 取 Address,不靠它做鉴权;Gate 验签通过才算数,SceneId 对不上说明票不是给这台 Gate 用的,要拒。
风险主要是别把 Payload 当可信权限、传输要用 TLS、生产要校过期,以及 token 泄露后的重放窗口要靠短效和运营侧吊销或版本控制收口。

参考文章
  • 2.JWT
  • 4.登录流程


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏