【直播切片工作台】第18章:认证与账号服务

简介: 本章详解认证与账号服务:登录防枚举(统一错误文案)、bcrypt密码安全三件套、逗号分隔角色模型、管理员创建账号、JWT携带用户信息免二次请求,以及stub驱动的service层测试实践。(239字)

第18章:认证与账号服务

本章分析登录链路的 service 侧(auth_service.go)、账号管理(account_service.go 与 handler),以及 pkg/utils/password.go 的密码工具与角色解析。登录是唯一不返回错误码细节的接口(防账号枚举),也是 JWT 生产线与 response 信封的第一次汇合。

流程

登录输入 username + password,处理分五步:查账号 → 比密码 → 查禁用状态 → 签发 JWT → 组装 LoginResult。其中前两步的失败信息刻意统一为「用户名或密码错误」——不管是用户不存在还是密码不对,客户端看到的同一句话,这是防账号枚举的标准做法(错误信息差异会泄露「哪些用户名存在」)。

flowchart TD
    A[POST /auth/login] --> B{用户名存在?}
    B -->|否| X[用户名或密码错误]
    B -->|是| C{bcrypt 比对通过?}
    C -->|否| X
    C -->|是| D{IsActive == 1?}
    D -->|否| Y[账号已被禁用]
    D -->|是| E[ParseRoles 解析角色]
    E --> F[GenerateToken 签发 JWT]
    F --> G[LoginResult: token+expires_in+用户信息]

LoginResult 除了 token 与 expires_in,还携带完整用户档案(ID/Username/Nickname/Avatar/Roles)——前端登录后立刻渲染用户菜单与权限,无需再发一次「获取当前用户」请求。

账号管理(accounts CRUD)是标准资源接口:创建/列表/详情/更新/删除,handler 从 AuthUser 取 created_by(created_by.go 统一处理这个横切关注点)。密码修改走 envinit 的 reset-password 或更新接口(更新时同样经 HashPassword 处理)。

实现

实现要点:

  • 错误分流:GetByUsername 返回 gorm.ErrRecordNotFound 时转换为统一错误;其他 DB 错误原样上抛(500)。仓储错误码不外泄到客户端。
  • 密码存储:utils.HashPassword / utils.ComparePassword(bcrypt 家族实现,password_test.go 验证往返);Account.Password 标签 json:"-" 序列化永远隐藏。比对用恒定时间比较防时序侧信道(bcrypt 库内建)。
  • 角色模型:Account.Roles 是逗号分隔字符串(如 admin,operator),utils.ParseRoles 切成 []string 进 JWT Claims。字符串存储简单直接,权限判断目前只在 UI 层(前端按 Roles 渲染菜单),后端接口未做细粒度 RBAC——单体小团队的合理起点。
  • IsActive int8 而非 bool:0/1 整型与 DB default 1 配合,GORM 零值语义明确(IsActive != 1 即禁用)。
  • auth_test.go / account_repo_stub_test.go:用 stub 仓储覆盖登录成功、密码错、禁用、不存在四个分支——service 层测试不碰数据库的范例。

v2 路由还有一个 handler/v2/account.go——账号接口的 v2 版本(当前与 v1 行为相近,为后续接口演进预留的平行空间,第 19 章路由注册可见)。

📌 设计决策

  • 无注册接口:账号由管理员创建,闭合的用户面配企业内部使用定位;开放注册需补邮箱验证、防灌水等一整套机制,目前不值得。
  • 登录失败统一文案 + 禁用单独文案:禁用状态不算敏感信息(需要先知道账号存在才可能被禁用提示),且对真实用户排障价值大。
  • expires_in 随 token 返回:前端可做「临期静默续登」的体验优化(快过期时后台重新登录)。

代码示例

登录主流程(注释保留原意):

// internal/service/auth_service.go(节选)
func (s *authService) Login(ctx context.Context, username, password string) (*LoginResult, error) {
   
    account, err := s.accountRepo.GetByUsername(ctx, username)
    if err != nil {
   
        if errors.Is(err, gorm.ErrRecordNotFound) {
   
            return nil, errors.New("用户名或密码错误") // 防枚举:与密码错误同文案
        }
        return nil, err
    }
    if !utils.ComparePassword(account.Password, password) {
   
        return nil, errors.New("用户名或密码错误")
    }
    if account.IsActive != 1 {
   
        return nil, errors.New("账号已被禁用")
    }
    roles := utils.ParseRoles(account.Roles)

    // 签发 JWT,将常用用户信息写入 Claims,后续请求可直接从 Token 读取
    token, err := jwtpkg.GenerateToken(s.jwtSecret, s.expiresIn, jwtpkg.UserClaims{
   
        UserID: account.ID, Username: account.Username,
        Nickname: account.Nickname, Avatar: account.Avatar, Roles: roles,
    })
    if err != nil {
   
        return nil, fmt.Errorf("生成 Token 失败: %w", err)
    }
    return &LoginResult{
   Token: token, ExpiresIn: s.expiresIn,
        ID: strconv.FormatUint(uint64(account.ID), 10), /* ... */}, nil
}

小结

  • 登录五步:查→比→禁→签→回;失败文案统一防枚举。
  • bcrypt 工具 + json:"-" + 恒定时间比较构成密码安全三件套。
  • 角色是逗号串,RBAC 留在 UI 层;账号由管理员创建,无开放注册。

思考题

  1. 若要加登录失败次数限制(防爆破),计数状态放内存、数据库还是 Redis?各自的重启语义如何?
  2. Roles 从字符串升级为角色表时,JWT Claims 与 GetAuthUser 的契约如何平滑迁移?

项目信息

  • GitHub仓库:Chyona/live-mixer
相关文章
|
9天前
|
Ubuntu Linux iOS开发
【2026最新版】VirtualBox下载安装保姆级教程(从零搭建VirtualBox虚拟机)
VirtualBox 是免费开源的跨平台虚拟机软件,支持 Windows/macOS/Linux 宿主机,可同时运行多个操作系统(如 Windows、Linux),用于测试、开发与学习。具备文件共享、剪贴板互通、USB 设备支持等功能,需安装扩展包启用高级特性。图形性能弱于 VMware,但轻量易用。(239 字)
|
开发工具
新人乘风者礼品兑换指南
仅限2023年11月15日(含11月15日)后入驻博主用于兑换礼品,此前完成入驻的博主按原邮寄方式进行。
5025 9
|
人工智能
上车吧,1000+claw概念域名来袭!
风口真正值钱的,从来不是最热闹的那一天,而是热闹之后,产品开始成片长出来的那一刻…
|
开发者 程序员
阿里云开发者档案能力鉴定说明
开发者能力鉴定是通过“技能测试”(通用技术能力)以及“阿里云认证”(阿里云解决方案能力)两个模块对您的技术能力进行一个较为全面的评估。
99388 8
|
3月前
|
人工智能
Qwen3.8抢先体验!正式版即将发布并开源!
千问Qwen3.8即将开源,参数达2.4T,进化速度以“天”计,实力媲美Fable 5。预览版Qwen3.8-Max已上线阿里Token Plan等平台,限时优惠:日间Credits低至1折,夜间更优,个人/团队版月付仅35元起!
5873 214
|
对象存储 数据库 Serverless
2026年 | 10月云大使推广奖励规则
关联周期不分用户类型延至90天,老用户产品首购返利升至35%;单客户实付封顶20万元;后付费订单纳入返利;云大使企业认证亦可入驻。
118649 62
|
9天前
|
Ubuntu Unix Linux
【保姆级】POSIX pthread线程库是什么?一文搞懂
POSIX是统一类UNIX系统接口的国际标准,确保程序跨平台可移植;其子集pthread专规范多线程编程接口。遵循POSIX/pthread编写的程序可在Linux、BSD等系统无缝运行,具备标准化、成熟稳定、社区支持强等优势。
|
9天前
|
Java Windows
【保姆级】Java配置环境变量图文教程,超级详细
本文详细介绍了Windows 10系统下JDK环境变量配置的完整步骤:包括设置JAVA_HOME变量、将%JAVA_HOME%\bin添加至Path路径,以及通过cmd执行java -version命令验证配置是否成功,图文并茂,操作清晰易懂。
|
2天前
|
人工智能 JSON Linux
【保姆级】ComfyUI部署教程(下载+安装+配置+工作流,2026最新)
ComfyUI 是一款开源节点式AI生成工具,支持图像、视频、音频及3D内容创作。通过拖拽连线组合模型加载、提示词、采样等节点,构建可复用、易修改的工作流,兼容SD1.5、SDXL、Flux、Qwen Image等主流模型。
|
10天前
|
人工智能 运维 安全
AI 赋能多渠道自适应钓鱼训练技术与实践研究
本文剖析AI时代自适应钓鱼训练技术,以Hoxhunt平台为样本,解析多渠道仿真、实时微培训、AI语音交互等核心模块,强调从“合规打卡”转向“行为改变”,指出其可提升员工防御能力,但不能替代技术防护,需构建人机协同的纵深防御体系。(239字)
54 0

热门文章

最新文章