位置:首页 > 进阶教程 > 程序员自救转型手记:PHP到AI+Golang目录与Token系统更新

程序员自救转型手记:PHP到AI+Golang目录与Token系统更新

时间:2026-07-25  |  作者:318050  |  阅读:0

欢迎继续我们的 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/

这个方案最大的问题是,像 databasecaptchaupload 这些东西,非常偏底层,属于基础设施。而 handlermodel 这些东西,是业务层。硬把它们塞在一起,总觉得不太对劲。

所以,我决定再加一层,叫做 infra,专门用来存放这些基础设施。调整后的结构看起来就清爽多了:

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

这里稍微解释一下:routerresponse 我没有移进去。原因很简单,router 是业务的入口,跟业务层放一起天经地义;response 可以看作是业务的出口,也有点类似于中间件,可移可不移,我选择不移。

另外,之前项目的配置解析逻辑(config/config.go 文件,注意不是 yaml 配置文件)本身也属于基础设施的一部分,最理想的归宿自然就是 internal/infra/config/config.go。既然有了 infra 目录,顺手就把它迁过去了。在 AI 时代,这种需求真的只需要一句话,让Claude Code(简称 cc)帮你搞定就行,基本不会出问题。

对了,友情提示一下:config/*.yaml 这些运行时配置文件不用动,放在项目根目录的 /config 下,这是符合社区习惯的做法,别挪错了。

Token 系统的正式搭建

结构搭好了,接下来就是重头戏——完善 token 系统。我的规划如下:

  1. 模型定义:在 internal/model/common.go 里定义一个 Token 模型,包含 token值、类型(字符串)、用户ID、创建时间、过期时间这些字段,所有字段都要带中文注释。
  2. 多驱动架构:在 internal/infra/token/token.go 里建立一个 token 管理接口和结构体。所有具体驱动放在 internal/infra/token/driver/ 目录下,一个驱动一个文件。目前只实现 database 驱动,未来可以无缝扩展 Redis 等。
  3. 动态加载机制:增加一个 token.driver 配置项,默认值是 database。管理器根据配置自动加载对应的驱动实例。
  4. 接口方法:每个驱动需要实现 CreateGetDeleteClear(清除指定用户指定类型的所有 token)这四个方法。管理器则额外暴露一个 Check 方法,用于检查 token 是否存在且未过期。
  5. 强制加密:入库的 token 值必须使用 SHA256 加密。

目前这个版本,还没有考虑加全局秘钥,也没搞“SHA256索引 + bcrypt校验”这种双保险。但配合后端的接口节流,即便 token 的 SHA256 值泄露了,想要暴力破解也是相当困难的。先把底子打好,未来再迭代优化。

把上面这些规划丢给 cc 之后,它生成的代码基本上就是我要的样子。我们来看看核心代码:

首先是配置文件增加驱动选项:

# config/config.yaml
token:
  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.go
package 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.go
package driver

// Database 基于关系型数据库的令牌驱动
type Database struct{}

// NewDatabase 创建数据库令牌驱动
func NewDatabase() *Database { ... }

// Create / Get / Delete / Clear 的具体实现
// 其中 Get 方法如果查不到记录,返回 nil, nil,方便上层判断
// Clear 方法会删除指定用户所有指定类型的 token
// ...

代码的具体实现细节,大家可以对照源码来看,这里就不逐行解释了。重要的是这套“多驱动 + 强制加密 + 灵活校验”的设计思路,可以很好地应对未来的变化。

今天的任务到这就算搞定了。目录结构更清晰了,token 系统也支棱起来了,而且我们用实际行动给 AI上了一课:安全,不能只靠理论上的不可行性,还得靠实践上的加固。

下一期,我们该聊点什么?评论区见。

程序员自救转型手记:PHP到AI+Golang目录与Token系统更新_wishdown.com

来源:整理自互联网
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多