程序员转型手记:PHP到AI+Golang,目录结构更新与token系统入库无需加密?
欢迎继续我们的 Go 语言学习与项目实战系列。上一回,我们已经把网络请求的封装和诸多细节都处理到位了,今天直接进入正题:一是进一步优化项目目录结构,二是把 token 系统打磨得更加完善。
事情还要从一个小插曲说起。
先聊聊那个关于 Token 的小插曲
在动手完善 token 系统之前,我特意给 AI 出了个“考题”。问题是:管理员身份令牌的值,我打算用 UUID v7 来生成,那么入库的时候,还有必要再加密一次吗?
结果你猜AI怎么答的?它很干脆地告诉我“不需要”。理由是 UUID v7 本身的结构(48位时间戳 + 74位随机数)已经足够安全,想要暴力枚举一个128位的UUID,在计算上基本是不可行的。它甚至还给我列了一堆关于“哈希的代价”和“真正需要加哈希的场景”的分析。
看完这个答案,我当时就愣住了。这不扯淡吗?
安全最大的敌人是谁?是“拖库”。数据库一旦泄露,黑客拿到的是明文 token,那人家不就直接可以登录后台了?但如果你对 token 做了哈希加密,那么黑客即便拿到了数据库,也得再费劲去破解你的加密,甚至还得同时拿到你的程序源码,才能模拟出一个有效的 token 来发起攻击。这相当于加了一把安全锁,怎么能说不加密呢?
所以,这事坚定了我的判断:在安全这件事上,不能完全迷信 AI 的结论,必须有自己的坚持。最终我们的 token 入库,必须用 SHA256 加密。
目录结构的调整:该分家时就分家
好了,说回正题。先来调整一下项目结构。之前我们的数据库初始化函数放在 internal/database/database.go 里。但接下来,token、captcha、upload 这些模块都会陆续加进来。如果继续按原来的规划,目录会变得很杂:
├── internal/
这个方案最大的问题是,像 database、captcha、upload 这些东西,非常偏底层,属于基础设施。而 handler、model 这些东西,是业务层。硬把它们塞在一起,总觉得不太对劲。
所以,我决定再加一层,叫做 infra,专门用来存放这些基础设施。调整后的结构看起来就清爽多了:
├── internal/│ ├── infra/
│ │ ├── token/
│ │ │ ├── driver/
│ │ │ │ ├── database.go
│ │ │ │ └── redis.go
│ │ │ └── token.go
│ │ ├── captcha/
│ │ └── upload/
│ ├── handler/
│ ├── model/
│ ├── repository/
│ ├── router/
│ ├── response/
│ ├── middleware/
│ └── service/
这里稍微解释一下:router 和 response 我没有移进去。原因很简单,router 是业务的入口,跟业务层放一起天经地义;response 可以看作是业务的出口,也有点类似于中间件,可移可不移,我选择不移。
另外,之前项目的配置解析逻辑(config/config.go 文件,注意不是 yaml 配置文件)本身也属于基础设施的一部分,最理想的归宿自然就是 internal/infra/config/config.go。既然有了 infra 目录,顺手就把它迁过去了。在 AI 时代,这种需求真的只需要一句话,让Claude Code(简称 cc)帮你搞定就行,基本不会出问题。
对了,友情提示一下:config/*.yaml 这些运行时配置文件不用动,放在项目根目录的 /config 下,这是符合社区习惯的做法,别挪错了。
Token 系统的正式搭建
结构搭好了,接下来就是重头戏——完善 token 系统。我的规划如下:
- 模型定义:在
internal/model/common.go里定义一个 Token 模型,包含 token值、类型(字符串)、用户ID、创建时间、过期时间这些字段,所有字段都要带中文注释。 - 多驱动架构:在
internal/infra/token/token.go里建立一个 token 管理接口和结构体。所有具体驱动放在internal/infra/token/driver/目录下,一个驱动一个文件。目前只实现 database 驱动,未来可以无缝扩展 Redis 等。 - 动态加载机制:增加一个
token.driver配置项,默认值是database。管理器根据配置自动加载对应的驱动实例。 - 接口方法:每个驱动需要实现
Create、Get、Delete、Clear(清除指定用户指定类型的所有 token)这四个方法。管理器则额外暴露一个Check方法,用于检查 token 是否存在且未过期。 - 强制加密:入库的 token 值必须使用 SHA256 加密。
目前这个版本,还没有考虑加全局秘钥,也没搞“SHA256索引 + bcrypt校验”这种双保险。但配合后端的接口节流,即便 token 的 SHA256 值泄露了,想要暴力破解也是相当困难的。先把底子打好,未来再迭代优化。
把上面这些规划丢给 cc 之后,它生成的代码基本上就是我要的样子。我们来看看核心代码:
首先是配置文件增加驱动选项:
# config/config.yamltoken:
driver: database
然后是模型定义:
// internal/model/common.go// Token 令牌模型,用于存储各类用户令牌
type Token struct {
Token string `gorm:"comment:令牌;type:varchar(64);primaryKey" json:"-"`
Type string `gorm:"comment:令牌类型;type:varchar(32);not null" json:"type"`
UserID uint `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.gopackage token
// ... 导入必要的包
// Driver 令牌存储驱动接口
type Driver interface { ... }
// Manager 令牌管理器,封装了加解密逻辑和 Check 方法
type Manager struct {
driver Driver
}
// NewManager 创建令牌管理器
func NewManager(driver Driver) *Manager { ... }
// Create 创建令牌,入库前自动对 Token 做 SHA256
func (m *Manager) Create(ctx context.Context, token *model.Token) error { ... }
// Get 获取令牌信息,返回时自动解密? 不,我们只存密文,拿密文去查
func (m *Manager) Get(ctx context.Context, token string) (*model.Token, error) { ... }
// Check 检查令牌是否存在且未过期
func (m *Manager) Check(ctx context.Context, token string) bool { ... }
// ... 其他方法
// 全局单例
func Instance() *Manager { ... }
// newDriver 根据配置创建存储驱动
func newDriver(name string) Driver { ... }
最后是数据库驱动的具体实现:
// internal/infra/token/driver/database.gopackage driver
// Database 基于关系型数据库的令牌驱动
type Database struct{}
// NewDatabase 创建数据库令牌驱动
func NewDatabase() *Database { ... }
// Create / Get / Delete / Clear 的具体实现
// 其中 Get 方法如果查不到记录,返回 nil, nil,方便上层判断
// Clear 方法会删除指定用户所有指定类型的 token
// ...
代码的具体实现细节,大家可以对照源码来看,这里就不逐行解释了。重要的是这套“多驱动 + 强制加密 + 灵活校验”的设计思路,可以很好地应对未来的变化。
今天的任务到这就算搞定了。目录结构更清晰了,token 系统也支棱起来了,而且我们用实际行动给 AI上了一课:安全,不能只靠理论上的不可行性,还得靠实践上的加固。
下一期,我们该聊点什么?评论区见。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
内网RPA离线部署从依赖打包到7×24无人值守踩坑与避坑方案
这三年,内网RPA项目接了不下二十个。每次开局都像闯关——断网、缺依赖、多机同步、定时执行、批量分发、源码保护、AI离线化,八个坑一个比一个深。今天把这些实战经验整理出来,希望能帮正在内网搞自动化的兄弟们少踩点雷。 一、内网无网络环境怎么部署RPA流程:先搞清楚什么叫“真离线” 很多工具宣传“支持本
水利工程师用WorkBuddy写洪水报告效率提升3倍
WorkBuddy开发者分享季 水利工程师AI提效实战:用WorkBuddy撰写洪水影响评价报告,效率提升3倍 WorkBuddy 效率 人工智能 开发工具 一、我是谁,为什么需要AI 先介绍一下自己——我是一名水利工程师,在湖南长沙的一家小型水利设计公司任职。当前行业环境不太
日志服务数据加工规则洞察仪表盘使用指南
数据加工诊断仪表盘 想实时掌握日志服务加工功能的运行状态?直接从加工列表页点击那个“规则洞察”按钮,仪表盘就会立刻呈现出来。入口就在那儿,不绕弯子。 跳转后,你可以按作业名称、实例ID或源LogStore来筛选任务状态。比如下边这张图,展示的是当前实例ID(90c9d47714dbb807d47c1
基于RFID的固定资产管理系统技术架构与工程实践
固定资产管理难题是众多企事业单位的普遍困扰,资产数量动辄数千件,且广泛分布于不同部门、楼层乃至园区。传统人工盘点方式在工程维度上始终面临三大关键瓶颈:采集效率低下、数据闭环中断、状态同步滞后。使用条码枪逐一扫描标签,识别距离通常不超过30厘米,操作人员需逐个寻找并扫描,盘点效率完全受限于人力。面对5
WorkBuddy实战用AI搭建A股智能盯盘助手省心高效
炒股的朋友们想必都深有体会——每天重复盯盘、查行情、分析板块轮动,这一整套流程下来耗费大量精力。手动翻查数据不仅身心俱疲,还很容易错过关键买卖节点。今天我们就来聊聊如何打造一款趁手的盯盘工具,借助AI替你分担这些重复性工作。 背景:盯盘的核心痛点 股民都有同感——每天不只要查询单只股票的实时行情,还
- 日榜
- 周榜
- 月榜
相关攻略
2026-07-02 12:28
2026-07-02 12:27
2026-07-02 12:27
2026-07-02 12:27
2026-07-02 12:27
2026-07-02 12:27
2026-07-02 12:26
2026-07-02 12:26
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程
热门话题

