Files
backend/internal/handler/captcha_handler.go

109 lines
2.7 KiB
Go
Raw Normal View History

package handler
import (
"net/http"
"carrotskin/internal/container"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// CaptchaHandler 验证码处理器
type CaptchaHandler struct {
container *container.Container
logger *zap.Logger
}
// NewCaptchaHandler 创建CaptchaHandler实例
func NewCaptchaHandler(c *container.Container) *CaptchaHandler {
return &CaptchaHandler{
container: c,
logger: c.Logger,
}
}
// CaptchaVerifyRequest 验证码验证请求
type CaptchaVerifyRequest struct {
CaptchaID string `json:"captchaId" binding:"required"`
Dx int `json:"dx" binding:"required"`
}
// Generate 生成验证码
// @Summary 生成滑动验证码
// @Description 生成滑动验证码图片
// @Tags captcha
// @Accept json
// @Produce json
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
// @Success 200 {object} map[string]interface{} "生成成功 {code: 200, message: string, data: {masterImage, tileImage, captchaId, y}}"
// @Failure 500 {object} map[string]interface{} "生成失败"
// @Router /api/v1/captcha/generate [get]
func (h *CaptchaHandler) Generate(c *gin.Context) {
masterImg, tileImg, captchaID, y, err := h.container.CaptchaService.Generate(c.Request.Context())
if err != nil {
h.logger.Error("生成验证码失败", zap.Error(err))
c.JSON(http.StatusInternalServerError, gin.H{
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
"code": 500,
"message": "生成验证码失败",
})
return
}
c.JSON(http.StatusOK, gin.H{
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
"code": 200,
"message": "操作成功",
"data": gin.H{
"masterImage": masterImg,
"tileImage": tileImg,
"captchaId": captchaID,
"y": y,
},
})
}
// Verify 验证验证码
// @Summary 验证滑动验证码
// @Description 验证用户滑动的偏移量是否正确
// @Tags captcha
// @Accept json
// @Produce json
// @Param request body CaptchaVerifyRequest true "验证请求"
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
// @Success 200 {object} map[string]interface{} "验证结果 {code: 200/400, message: string}"
// @Failure 400 {object} map[string]interface{} "参数错误"
// @Router /api/v1/captcha/verify [post]
func (h *CaptchaHandler) Verify(c *gin.Context) {
var req CaptchaVerifyRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
"code": 400,
"message": "参数错误: " + err.Error(),
})
return
}
valid, err := h.container.CaptchaService.Verify(c.Request.Context(), req.Dx, req.CaptchaID)
if err != nil {
h.logger.Error("验证码验证失败",
zap.String("captcha_id", req.CaptchaID),
zap.Error(err),
)
c.JSON(http.StatusInternalServerError, gin.H{
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
"code": 500,
"message": "验证失败",
})
return
}
if valid {
c.JSON(http.StatusOK, gin.H{
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
"code": 200,
"message": "验证成功",
})
} else {
c.JSON(http.StatusOK, gin.H{
refactor(yggdrasil): 整理与性能优化,修复若干 Bug Bug 修复 - textures metadata:SKIN 仅在 IsSlim 时输出 {"model":"slim"};CAPE 不带 metadata。 原实现误用文件字节数 skin.Size 作为 metadata,违反 Yggdrasil 协议。 - KeyPair 持久化不全:Profile 新增 rsa_public_key/public_key_signature/ public_key_signature_v2/key_expires_at/key_refresh_at 列;GetKeyPair/UpdateKeyPair 读写全部字段。AutoMigrate 自动加列。原实现每次请求都重新生成 RSA-4096。 - GetPlayerCertificates:无效 token 返回 401(先前误用 403 且未判 err)。 - HasJoinedServer:失败返回 204 无 body,符合 Yggdrasil 协议(原用 APIResponse + body 违反 204 规范)。 代码质量 - Authenticate 删除冗余 body 读取与回放。 - 证书服务引入具名结构 PlayerCertificate/PlayerKeyPair,替代 map[string]interface{}。 - CreateSession 用户名缺失改用 ErrUsernameRequired(新增)。 性能优化(签名一致性的回归测试已覆盖) - SignatureService 缓存已解析的根私钥(sync.RWMutex 双重检查), 快路径仅一次 RLock + RSA 签名,免去每次签名 PEM 解析与 Redis 往返。 - GetOrCreateYggdrasilKeyPair 用 MGet 单次往返取三字段,缓存命中后零 Redis。 - NewKeyPair 消息构造用 strconv.AppendInt 避免 string+拼接分配;V2 复用 DER 字节。 - 序列化服务:texturesMap 预分配 cap(2);slim 分支直接构造完整 map。 - 会话服务 GetSession 移除重复的 ValidateServerID 校验。 死代码清理 - 删除 yggdrasil_validator.go(未被调用的 Validator)。 - 删除 signature_service.FormatPublicKey/SignStringWithProfileRSA。 - 删除 pkg/auth 中未被使用的 YggdrasilJWTManager 与 GenerateKeyPair/ EncodePrivateKeyToPEM/RedisClient/YggdrasilPrivateKeyRedisKey。 - 删除 yggdrasil_handler.go 中 25 个未使用常量、passwordRegex、 APIResponse/standardResponse。 - 删除 errors.go 中未被使用的 ErrYggForbiddenOperation/ErrYggIllegalArgument/ ErrInvalidSignature/ErrInvalidTextureType/ErrCertificateGenerate/ErrInvalidPassword。 测试 - 新增 signature_service_test.go(基于 miniredis):8 个测试 + 基准。 核心:SignString_MatchesReference 与重构前参考实现逐字节比对签名输出一致。 -race 检测通过;基准约 7.1ms/op(缓存命中路径)。 附带(与本次任务前已存在的未提交改动) - handler/captcha_handler:将响应字段 msg 改为 message,与前端约定对齐。
2026-07-09 17:18:26 +08:00
"code": 400,
"message": "验证失败,请重试",
})
}
}