f
This commit is contained in:
@@ -2,9 +2,11 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.uber.org/zap"
|
||||
@@ -27,6 +29,7 @@ type UserHandler struct {
|
||||
logger *zap.Logger
|
||||
jwtAuth *middleware.JWTAuthMiddleware
|
||||
config *config.Config
|
||||
cache interfaces.CacheService
|
||||
}
|
||||
|
||||
// NewUserHandler 创建用户处理器
|
||||
@@ -37,6 +40,7 @@ func NewUserHandler(
|
||||
logger *zap.Logger,
|
||||
jwtAuth *middleware.JWTAuthMiddleware,
|
||||
cfg *config.Config,
|
||||
cache interfaces.CacheService,
|
||||
) *UserHandler {
|
||||
return &UserHandler{
|
||||
appService: appService,
|
||||
@@ -45,6 +49,7 @@ func NewUserHandler(
|
||||
logger: logger,
|
||||
jwtAuth: jwtAuth,
|
||||
config: cfg,
|
||||
cache: cache,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,15 +105,18 @@ func (h *UserHandler) SendCode(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 如果启用了签名验证,进行签名校验
|
||||
// 如果启用了签名验证,进行签名校验(包含nonce唯一性检查,防止重放攻击)
|
||||
if h.config.SMS.SignatureEnabled {
|
||||
if err := h.verifyDecodedSignature(decodedData); err != nil {
|
||||
if err := h.verifyDecodedSignature(c.Request.Context(), decodedData); err != nil {
|
||||
h.logger.Warn("短信发送签名验证失败",
|
||||
zap.String("phone", decodedData.Phone),
|
||||
zap.String("scene", decodedData.Scene),
|
||||
zap.String("client_ip", c.ClientIP()),
|
||||
zap.Error(err))
|
||||
h.response.BadRequest(c, "签名验证失败,请求无效")
|
||||
|
||||
// 根据错误类型返回不同的用户友好消息(不暴露技术细节)
|
||||
userMessage := h.getSignatureErrorMessage(err)
|
||||
h.response.BadRequest(c, userMessage)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -150,8 +158,8 @@ func (h *UserHandler) decodeRequestData(encodedData string) (*decodedSendCodeDat
|
||||
return &decoded, nil
|
||||
}
|
||||
|
||||
// verifyDecodedSignature 验证解码后的签名
|
||||
func (h *UserHandler) verifyDecodedSignature(data *decodedSendCodeData) error {
|
||||
// verifyDecodedSignature 验证解码后的签名(包含nonce唯一性检查,防止重放攻击)
|
||||
func (h *UserHandler) verifyDecodedSignature(ctx context.Context, data *decodedSendCodeData) error {
|
||||
// 构建参数map(包含signature字段,VerifySignature会自动排除它)
|
||||
params := map[string]string{
|
||||
"phone": data.Phone,
|
||||
@@ -159,15 +167,40 @@ func (h *UserHandler) verifyDecodedSignature(data *decodedSendCodeData) error {
|
||||
"signature": data.Signature,
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
return crypto.VerifySignature(
|
||||
// 验证签名并检查nonce唯一性(防止重放攻击)
|
||||
return crypto.VerifySignatureWithNonceCheck(
|
||||
ctx,
|
||||
params,
|
||||
h.config.SMS.SignatureSecret,
|
||||
data.Timestamp,
|
||||
data.Nonce,
|
||||
h.cache,
|
||||
"sms:signature", // 缓存键前缀
|
||||
)
|
||||
}
|
||||
|
||||
// getSignatureErrorMessage 根据错误类型返回用户友好的错误消息(不暴露技术细节)
|
||||
func (h *UserHandler) getSignatureErrorMessage(err error) string {
|
||||
errMsg := err.Error()
|
||||
|
||||
// 根据错误消息内容判断错误类型,返回通用的用户友好消息
|
||||
if strings.Contains(errMsg, "请求已被使用") || strings.Contains(errMsg, "重复提交") {
|
||||
// 重放攻击:返回通用消息,不暴露具体原因
|
||||
return "请求无效,请重新操作"
|
||||
}
|
||||
if strings.Contains(errMsg, "时间戳") || strings.Contains(errMsg, "过期") {
|
||||
// 时间戳过期:返回通用消息
|
||||
return "请求已过期,请重新操作"
|
||||
}
|
||||
if strings.Contains(errMsg, "签名") {
|
||||
// 签名错误:返回通用消息
|
||||
return "请求验证失败,请重新操作"
|
||||
}
|
||||
|
||||
// 其他错误:返回通用消息
|
||||
return "请求验证失败,请重新操作"
|
||||
}
|
||||
|
||||
|
||||
// Register 用户注册
|
||||
// @Summary 用户注册
|
||||
|
||||
Reference in New Issue
Block a user