@@ -15,7 +15,6 @@ import (
1515 "github.com/chaitin/MonkeyCode/backend/db"
1616 "github.com/chaitin/MonkeyCode/backend/domain"
1717 "github.com/chaitin/MonkeyCode/backend/errcode"
18- "github.com/chaitin/MonkeyCode/backend/pkg/crypto"
1918 "github.com/chaitin/MonkeyCode/backend/pkg/cvt"
2019)
2120
@@ -159,16 +158,12 @@ func (u *UserUsecase) SendBindEmailVerification(ctx context.Context, userID uuid
159158 return errcode .ErrEmailTaken
160159 }
161160
162- // 生成验证 token
163- token , err := crypto .Simple (userID .String (), time .Now ().Add (time .Hour * 24 ))
164- if err != nil {
165- u .logger .ErrorContext (ctx , "generate bind email token failed" , "error" , err )
166- return errcode .ErrInternalServer .Wrap (err )
167- }
161+ // 生成验证 token(使用 UUID,避免 base32 填充字符在邮件传输中被破坏)
162+ token := uuid .NewString ()
168163
169- // 存储 token 到 Redis,格式: {token}:{email},有效期 24 小时
170- key := fmt .Sprintf ("bind_email_token:%s" , userID . String () )
171- value := fmt .Sprintf ("%s:%s" , token , req .Email )
164+ // 存储 token 到 Redis,key: bind_email_token: {token},value: {userID }:{email},有效期 24 小时
165+ key := fmt .Sprintf ("bind_email_token:%s" , token )
166+ value := fmt .Sprintf ("%s:%s" , userID . String () , req .Email )
172167 if err := u .redis .Set (ctx , key , value , time .Hour * 24 ).Err (); err != nil {
173168 u .logger .ErrorContext (ctx , "set redis key failed" , "error" , err )
174169 return errcode .ErrDatabaseOperation .Wrap (err )
@@ -194,21 +189,8 @@ func (u *UserUsecase) SendBindEmailVerification(ctx context.Context, userID uuid
194189
195190// VerifyBindEmail 验证邮箱绑定
196191func (u * UserUsecase ) VerifyBindEmail (ctx context.Context , token string ) error {
197- // 验证 token 的有效性(检查签名和过期时间)
198- userIDStr , err := crypto .ValidateSimple (token )
199- if err != nil {
200- u .logger .WarnContext (ctx , "validate token failed" , "error" , err )
201- return errcode .ErrEmailVerifyFailed .Wrap (err )
202- }
203-
204- userID , err := uuid .Parse (userIDStr )
205- if err != nil {
206- u .logger .WarnContext (ctx , "parse user id from token failed" , "error" , err )
207- return errcode .ErrEmailVerifyFailed .Wrap (err )
208- }
209-
210- // 从 Redis 中取出存储的 token 和邮箱(一次性消费)
211- key := fmt .Sprintf ("bind_email_token:%s" , userID .String ())
192+ // 以 token 为 key 从 Redis 中取出 userID 和邮箱(一次性消费)
193+ key := fmt .Sprintf ("bind_email_token:%s" , token )
212194 redisValue , err := u .redis .GetDel (ctx , key ).Result ()
213195 if err != nil {
214196 if err == redis .Nil {
@@ -218,21 +200,19 @@ func (u *UserUsecase) VerifyBindEmail(ctx context.Context, token string) error {
218200 return errcode .ErrDatabaseOperation .Wrap (err )
219201 }
220202
221- // 解析 Redis 中的值:{token }:{email}
203+ // 解析 Redis 中的值:{userID }:{email}
222204 parts := strings .SplitN (redisValue , ":" , 2 )
223205 if len (parts ) != 2 {
224206 u .logger .WarnContext (ctx , "invalid redis value format" , "value" , redisValue )
225207 return errcode .ErrEmailVerifyFailed
226208 }
227209
228- storedToken := parts [0 ]
229- email := parts [1 ]
230-
231- // 验证 token 是否匹配(防止 token 替换)
232- if storedToken != token {
233- u .logger .WarnContext (ctx , "token mismatch" )
234- return errcode .ErrEmailVerifyFailed
210+ userID , err := uuid .Parse (parts [0 ])
211+ if err != nil {
212+ u .logger .WarnContext (ctx , "parse user id from redis value failed" , "error" , err )
213+ return errcode .ErrEmailVerifyFailed .Wrap (err )
235214 }
215+ email := parts [1 ]
236216
237217 // 再次检查邮箱是否被其他用户占用(防止竞态条件)
238218 existingUsers , err := u .repo .GetUserByEmail (ctx , []string {email })
0 commit comments