我有一张用户表,用户表里面的一个字段叫做points 积分,表示用户当前的剩余积分数据的。每当使用积分兑换物品,积分就会减少。
// 用户表
type User struct {BaseModelAccount string `json:"account" form:"account" binding:"required" gorm:"column:account;type:varchar(64);not null;comment:账号,默认同TapId;"` //账号(同ID)Password string `json:"password" form:"password" binding:"required" gorm:"column:password;type:varchar(64);default:'666666';comment:密码;"` //密码,默认666666Mobile string `json:"mobile" form:"mobile" gorm:"column:mobile;size:32;default:'';comment:手机号;"` //手机号,非必须Nickname string `json:"nickname" form:"nickname" gorm:"column:nickname;size:64;default:'';comment:昵称;"` //手机号,非必须QQID string `json:"qq_id" form:"qq_id" gorm:"size:128;default:'';comment:QQID;"` //QQ ID(非必须)WechatID string `json:"wechat_id" form:"wechat_id" gorm:"size:128;default:'';comment:微信ID;"` //微信ID(非必须)Points int64 `json:"points" form:"points" gorm:"default:0;comment:广告积分;"` //当前广告积分,默认0TotalPoints int64 `json:"total_points" form:"total_points" gorm:"default:0;comment:总积分;"` //总共获得的广告积分,默认0
}
代码是这么写的
user.Points -= totalNeedPoints
Model.GetDB().Updates(&user)
使用掉积分,然后保存到数据库中,看起来没有问题
问题是这么发生的:
最近,追踪日志发现,一个用户的积分变化是这样的。
做了A,+100 积分
做了B,+ 200 积分
然后兑换了C,-300积分
然后做了D,+100积分。这时候发现,用户的剩余积分居然是400?!!!
经过定位分析,代码就出现在上面的那两行,后面优化成下面的代码
data := make(map[string]interface{})
data["points"] = user.Pointserr = Model.GetDB().Model(&Model.User{}).Where("id = ?", user.Id).Updates(data)
终于正常了!
原因复盘: 使用go语言的gorm库时,如果值为0,直接执行Updates更新模型,是不会保存到数据库里面去了。这样就会导致重复刷积分的漏洞出现。
加个标记,大家一起学习避坑。