news 2026/7/2 5:02:47

从 PHP 到 AI + Golang,程序员自救转型手记(十六):目录结构更新、完善 token 系统(AI 表示 token 入库无需加密?)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从 PHP 到 AI + Golang,程序员自救转型手记(十六):目录结构更新、完善 token 系统(AI 表示 token 入库无需加密?)

这是一个系列 Blog,作者将以一个 PHP 全栈工程师的身份,利用 AI 工具(claude code、codex、deepseek、豆包等):从零开始学习 golang 语言,并最终完成 ai-go-mall(github | gitee)开源项目的制作,全程记录分享。

在上一期,我们已经完成 “优化细节、网络请求封装”,本期将完成:目录结构更新、完善 token 系统

对 AI 的小考验

今天在完善 token 系统之前,特意考验了一下 AI :token 作为管理员身份令牌,其值生成打算使用UUID v7,入库是否还有必要加密

不需要。 UUID v7 的安全性已足够 UUID v7 结构为48位时间戳 +74位随机数,每秒可生成2^74 ≈1.8×10²² 个不重复值。暴力枚举一个128位的 UUID 在计算上不可行。 哈希的代价,巴拉巴拉... 真正该加哈希的场景,巴拉巴拉...

我去,这不对吧,加密最大的意义是防止被拖库,token 泄露,黑客直接就登录到后台了,而有加密的话黑客必须同时获得程序源码和 token 密文才能入侵到后台,怎么能不加密呢?

目录结构更新

新增 infra 目录

目前我们的数据库初始化函数放在internal/database/database.go文件中,考虑到接下来要增加的 token(多驱动设计)、captcha、upload(多驱动设计)等,按原来的计划,我们的目录结构未来会变成:

├── internal/ │ ├── handler/ │ ├── model/ │ ├── repository/ │ ├── router/ │ ├── database/ │ ├── captcha/ │ ├── upload/ │ ├── response/ │ ├── middleware/ │ └── service/

其中的 database、token、captcha、upload 非常的偏底层,和 handler、model 等业务层的有点不搭,所以我决定再加一层infra目录,存放基础设施,新的目录结构如下:

├── internal/ │ ├── infra/ │ │ ├── token/ │ │ │ ├── driver │ │ │ │ ├── database.go │ │ │ │ └── redis.go │ │ │ └─── token.go │ │ ├── captcha/ │ │ └── upload/ │ ├── handler/ │ ├── model/ │ ├── repository/ │ ├── router/ │ ├── response/ │ ├── middleware/ │ └── service/

即新增infra目录,将databasetokencaptchaupload这类偏底层的放于其中,routerresponse我没有选择移进去,其中router和业务层的放在一起是合理的,它是业务入口,response算是业务出口,属于可移可不移选择不移。

配置解析(config.go 文件)移入 infra 目录

项目是一个应用(非库),而 config 模块是项目内部实现细节,且属于带状态的基础设施,现在我们已经建立了infra目录,那么配置解析逻辑config/config.go文件,非yaml配置文件)最理想的存放位置当然是internal\infra\config\config.go,AI时代,我们直接让 cc 将其移入其中即可,这类需求只需要一句话,无需人工找文件替换,基本不会出问题,最多全项目搜索 /config 确定一下。

PS:config/*.yaml 无需移动,该文件属于运行时配置,放在 /config 是符合社区习惯的做法。

完善 token 系统

token 系统规划如下:

  1. 于 internal/model/common.go 建立 token 模型,有 token、type(字符串)、user_id、创建时间、过期时间字段,字段全部带有中文注释
  2. 于 internal/infra/token/token.go 建立 token 管理接口和结构体,使用多驱动模式,所有驱动存放于internal/infra/token/driver目录,一个驱动一个文件,目前实现 database 一种驱动
  3. 增加token.driver配置项,默认值为databaseinternal/infra/token/token.go内读取驱动配置,返回对应驱动的 token 管理实例。
  4. token 驱动实现Create、Get、Delete、Clear(删除指定会员指定类型的所有token)方法,token 管理器的结构体除驱动的所有方法外,额外实现Check方法(使用 Get 方法读取 token 信息后检查是否过期)
  5. token 入库使用 SHA256 加密

目前 token 系统还未考虑额外的全局秘钥(后续应该会考虑),也未考虑【SHA256 索引 + bcrypt 校验】双字段方案,但配合验权接口节流,就算泄露了 Token SHA256,抗爆破能力还是够的,将之前的规划发给 cc,最终核心代码如下:

# config/config.yaml 增加 token 驱动配置,目前只实现了 database 驱动# 未来可以增加 redis 等驱动,得益于 AI 的帮助,加驱动基本上只需要一句话token:driver:database
// internal\model\common.go 文件,用于存放 captcha、area 等公共模型// Token 令牌模型,用于存储各类用户令牌typeTokenstruct{Tokenstring`gorm:"comment:令牌;type:varchar(64);primaryKey" json:"-"`Typestring`gorm:"comment:令牌类型;type:varchar(32);not null" json:"type"`UserIDuint`gorm:"comment:用户ID;not null;index" json:"user_id"`CreatedAt time.Time`gorm:"comment:创建时间" json:"created_at"`ExpiredAt time.Time`gorm:"comment:过期时间;not null;index" json:"expired_at"`}
// internal\infra\token\token.go 文件,用于存放 token 管理接口和结构体packagetokenimport("context""crypto/sha256""fmt""sync""time""ai-go-mall/internal/infra/config""ai-go-mall/internal/infra/token/driver""ai-go-mall/internal/model")// Driver 令牌存储驱动接口typeDriverinterface{Create(ctx context.Context,token*model.Token)errorGet(ctx context.Context,tokenstring)(*model.Token,error)Delete(ctx context.Context,tokenstring)errorClear(ctx context.Context,userIDuint,tokenTypestring)error}// Manager 令牌管理器typeManagerstruct{driver Driver}// NewManager 创建令牌管理器funcNewManager(driver Driver)*Manager{return&Manager{driver:driver}}// Create 创建令牌,入库前自动对 Token 做 SHA256func(m*Manager)Create(ctx context.Context,token*model.Token)error{token.Token=sha256Hex(token.Token)returnm.driver.Create(ctx,token)}// Get 获取令牌信息func(m*Manager)Get(ctx context.Context,tokenstring)(*model.Token,error){returnm.driver.Get(ctx,sha256Hex(token))}// Check 检查令牌是否存在且未过期func(m*Manager)Check(ctx context.Context,tokenstring)bool{t,err:=m.Get(ctx,token)iferr!=nil||t==nil{returnfalse}returntime.Now().Before(t.ExpiredAt)}// Delete 删除令牌func(m*Manager)Delete(ctx context.Context,tokenstring)error{returnm.driver.Delete(ctx,sha256Hex(token))}// Clear 清除指定用户指定类型的所有令牌func(m*Manager)Clear(ctx context.Context,userIDuint,tokenTypestring)error{returnm.driver.Clear(ctx,userID,tokenType)}// sha256Hex 返回 raw 的 SHA256 十六进制字符串funcsha256Hex(rawstring)string{sum:=sha256.Sum256([]byte(raw))returnfmt.Sprintf("%x",sum)}// ==================== 全局单例 ====================var(instance*Manager once sync.Once)// Instance 返回全局令牌管理器实例,首次调用时根据配置自动初始化funcInstance()*Manager{once.Do(func(){instance=NewManager(newDriver(config.Get().Token.Driver))})returninstance}// newDriver 根据配置创建存储驱动funcnewDriver(namestring)Driver{switchname{default:returndriver.NewDatabase()}}
// internal\infra\token\driver\database.go 文件,token 数据库驱动packagedriverimport("context""errors""ai-go-mall/internal/infra/database""ai-go-mall/internal/model""gorm.io/gorm")// Database 基于关系型数据库的令牌驱动typeDatabasestruct{}// NewDatabase 创建数据库令牌驱动funcNewDatabase()*Database{return&Database{}}// Create 创建令牌func(d*Database)Create(ctx context.Context,t*model.Token)error{returngorm.G[model.Token](database.DB()).Create(ctx,t)}// Get 获取令牌信息func(d*Database)Get(ctx context.Context,tokenstring)(*model.Token,error){t,err:=gorm.G[model.Token](database.DB()).Where("token = ?",token).First(ctx)iferr!=nil{iferrors.Is(err,gorm.ErrRecordNotFound){returnnil,nil}returnnil,err}return&t,nil}// Delete 删除令牌func(d*Database)Delete(ctx context.Context,tokenstring)error{_,err:=gorm.G[model.Token](database.DB()).Where("token = ?",token).Delete(ctx)returnerr}// Clear 清除指定用户指定类型的所有令牌func(d*Database)Clear(ctx context.Context,userIDuint,tokenTypestring)error{_,err:=gorm.G[model.Token](database.DB()).Where("user_id = ? AND type = ?",userID,tokenType).Delete(ctx)returnerr}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/2 5:01:09

初识C语言的常见概念

Windows 与 Linux 下 C 编译工具链对比:MSVC MinGW GCC 本文系统梳理Windows平台下的 MSVC和MinGW与Linux平台下的GCC的区别。工具链全称 / 背景所属生态主要平台MSVCMicrosoft Visual C Compiler微软官方WindowsMinGWMinimalist GNU for WindowsGNU 开源社区Window…

作者头像 李华
网站建设 2026/7/2 5:00:12

2026年国产TF卡品牌哪家好?深度评测与选购指南

在无人机航拍、运动相机记录、Switch掌机扩容、行车记录仪循环录制以及智能手机拓展存储等场景中,TF卡(即microSD卡)已成为不可或缺的存储介质。然而,市面上的TF卡品牌繁多,参数虚标、读写掉速、高温环境下数据丢失等问…

作者头像 李华
网站建设 2026/7/2 5:00:11

嵌入式条形码识别系统开发与TM4C123优化实践

1. 项目背景与核心需求在工业自动化、零售仓储和智能设备领域,条形码识别技术一直是数据采集的核心环节。传统方案往往采用现成的扫码枪或工业相机,但在嵌入式设备集成、成本敏感或特殊环境应用中,自主开发条形码读取系统具有独特优势。EM308…

作者头像 李华
网站建设 2026/7/2 4:56:40

AI 视频智能体新手 7 天上手指南:从注册到第一条成片

很多人第一次听到"AI 视频智能体",第一反应是:又是另一种自动剪辑工具吧? 真不是。 AI 视频智能体和传统剪辑工具最大的区别,是它能把"找爆款、拆结构、写脚本、出视频、做封面、发多平台"这一整圈流程&#…

作者头像 李华
网站建设 2026/7/2 4:54:57

[Divide节点]原理解析与实际应用

理标量、向量和矩阵等多种数据类型,在材质动态控制、特效实现与性能优化中发挥关键作用。例如,在昼夜交替系统中,Divide节点可通过时间参数驱动场景光照的平滑过渡;在角色受伤特效中,它能精确控制屏幕红色渐变的强度。…

作者头像 李华