添加用户密码重置功能
This commit is contained in:
parent
0fc72a86d6
commit
395f1f681d
108
handler/user.go
108
handler/user.go
|
|
@ -28,6 +28,7 @@ func SetUpUserGroup(router *gin.Engine) {
|
||||||
userGroup.POST("/update", UpdateUserInfo)
|
userGroup.POST("/update", UpdateUserInfo)
|
||||||
userGroup.POST("/sync", GetSyncUserInfo)
|
userGroup.POST("/sync", GetSyncUserInfo)
|
||||||
userGroup.POST("/delete", DeleteUser)
|
userGroup.POST("/delete", DeleteUser)
|
||||||
|
userGroup.POST("/reset", ResetPassword)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RLReq struct {
|
type RLReq struct {
|
||||||
|
|
@ -415,3 +416,110 @@ func GetSyncUserInfo(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResetPasswordReq struct {
|
||||||
|
Email string `json:"email" form:"email"`
|
||||||
|
OldPassword string `json:"old_password" form:"old_password"`
|
||||||
|
NewPassword string `json:"new_password" form:"new_password"`
|
||||||
|
Type int `json:"type" form:"type"` //0获取验证码,2为邮箱验证码重置密码,1为旧密码重置密码
|
||||||
|
Code string `json:"code" form:"code"` //验证码
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResetPassword(c *gin.Context) {
|
||||||
|
var req_data ResetPasswordReq
|
||||||
|
if err := c.ShouldBind(&req_data); err == nil {
|
||||||
|
if req_data.Type == 0 {
|
||||||
|
//获取验证码
|
||||||
|
//查看是否存在该邮箱
|
||||||
|
user := dao.FindUserByEmail(req_data.Email)
|
||||||
|
if user.ID == 0 {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "邮箱不存在", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if worker.IsContainKey("reset_password_" + req_data.Email) {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "验证码已发送,请5分钟后再试", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//随机字符串验证码大写
|
||||||
|
code := worker.GetRandomString(6)
|
||||||
|
worker.SetRedisWithExpire("reset_password_"+req_data.Email, code, time.Minute*5) //设置5分钟过期`
|
||||||
|
//发送邮件
|
||||||
|
service.SendEmail(req_data.Email, "大学生学业作品AI生成工具开发重置密码", "验证码:"+code+" ,请在5分钟内使用!")
|
||||||
|
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "2"})
|
||||||
|
return
|
||||||
|
} else if req_data.Type == 1 {
|
||||||
|
//旧密码重置密码
|
||||||
|
if len(req_data.OldPassword) != 32 {
|
||||||
|
hasher := md5.New()
|
||||||
|
hasher.Write([]byte(req_data.OldPassword)) // 生成密码的 MD5 散列值
|
||||||
|
req_data.OldPassword = hex.EncodeToString(hasher.Sum(nil)) // 生成密码的 MD5 散列值
|
||||||
|
}
|
||||||
|
if len(req_data.NewPassword) != 32 {
|
||||||
|
hasher := md5.New()
|
||||||
|
hasher.Write([]byte(req_data.NewPassword)) // 生成密码的 MD5 散列值
|
||||||
|
req_data.NewPassword = hex.EncodeToString(hasher.Sum(nil)) // 生成密码的 MD5 散列值
|
||||||
|
}
|
||||||
|
user := dao.FindUserByEmail(req_data.Email)
|
||||||
|
if user.ID == 0 {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "邮箱不存在", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user.Password != req_data.OldPassword {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "旧密码错误", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user.Password == req_data.NewPassword {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "新旧密码相同", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dao.UpdateUserByID(int(user.ID), user.Name, req_data.NewPassword, user.Email)
|
||||||
|
var resp proto.ResponseOAuth
|
||||||
|
token, err2 := service.CreateTokenAndSave(user)
|
||||||
|
if err2 != nil {
|
||||||
|
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "new token error", "data": resp})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Token = token
|
||||||
|
resp.ID = user.ID
|
||||||
|
resp.Name = user.Name
|
||||||
|
resp.Email = user.Email
|
||||||
|
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp})
|
||||||
|
} else if req_data.Type == 2 {
|
||||||
|
//邮箱重置密码
|
||||||
|
if len(req_data.NewPassword) != 32 {
|
||||||
|
hasher := md5.New()
|
||||||
|
hasher.Write([]byte(req_data.NewPassword)) // 生成密码的 MD5 散列值
|
||||||
|
req_data.NewPassword = hex.EncodeToString(hasher.Sum(nil)) // 生成密码的 MD5 散列值
|
||||||
|
}
|
||||||
|
user := dao.FindUserByEmail(req_data.Email)
|
||||||
|
if user.ID == 0 {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "邮箱不存在", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
code := worker.GetRedis("reset_password_" + req_data.Email)
|
||||||
|
if code != req_data.Code {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "验证码错误", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dao.UpdateUserByID(int(user.ID), user.Name, req_data.NewPassword, user.Email)
|
||||||
|
token, err2 := service.CreateTokenAndSave(user)
|
||||||
|
if err2 != nil {
|
||||||
|
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "new token error", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var resp proto.ResponseOAuth
|
||||||
|
resp.Token = token
|
||||||
|
resp.ID = user.ID
|
||||||
|
resp.Name = user.Name
|
||||||
|
resp.Email = user.Email
|
||||||
|
c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp})
|
||||||
|
} else {
|
||||||
|
c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "type error", "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
c.JSON(200, gin.H{"code": proto.ParameterError, "message": err, "data": "2"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
var Config ConfigStruct
|
var Config ConfigStruct
|
||||||
var SigningKey = []byte{}
|
var SigningKey = []byte{}
|
||||||
var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true} // 不需要token验证的url
|
var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true, "/user/reset": true} // 不需要token验证的url
|
||||||
var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3}
|
var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3}
|
||||||
var File_Type = map[string]int{"im": 1, "avatar": 2, "file": 3, "config": 4} // 文件类型
|
var File_Type = map[string]int{"im": 1, "avatar": 2, "file": 3, "config": 4} // 文件类型
|
||||||
const (
|
const (
|
||||||
|
|
|
||||||
|
|
@ -110,3 +110,10 @@ type UpdateShellRespV2 struct {
|
||||||
ID uint `json:"id" form:"id"`
|
ID uint `json:"id" form:"id"`
|
||||||
Status int `json:"status" form:"status"`
|
Status int `json:"status" form:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ResponseOAuth struct {
|
||||||
|
ID uint `json:"id" form:"id"`
|
||||||
|
Name string `json:"name" form:"name"`
|
||||||
|
Email string `json:"email" form:"email"`
|
||||||
|
Token string `json:"token" form:"token"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/golang-jwt/jwt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -367,3 +368,35 @@ func ConfirmSyncUserData(device string, data proto.UserSyncConfirm) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 生成新的token,存入redis,返回信息
|
||||||
|
func CreateTokenAndSave(user dao.User) (string, error) {
|
||||||
|
var tokenString string
|
||||||
|
var err error
|
||||||
|
key := "user_" + user.Name
|
||||||
|
redis_token := worker.GetRedis(string(key))
|
||||||
|
if redis_token == "" {
|
||||||
|
// 生成 JWT 令牌
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
|
||||||
|
"username": user.Name,
|
||||||
|
"id": user.ID,
|
||||||
|
"exp": time.Now().Add(time.Hour * 10).Unix(), // 令牌过期时间, 10小时后过期
|
||||||
|
})
|
||||||
|
tokenString, err = token.SignedString(proto.SigningKey)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.SetRedisWithExpire("user_"+user.Name, tokenString, time.Hour*10) // 将用户信息存入
|
||||||
|
worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*10) // 设置过期时间为10分钟
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
data["id"] = user.ID
|
||||||
|
data["username"] = user.Name
|
||||||
|
data["email"] = user.Email
|
||||||
|
worker.SetHash(tokenString, data) // 将用户信息存入
|
||||||
|
} else {
|
||||||
|
tokenString = redis_token
|
||||||
|
}
|
||||||
|
// 返回令牌
|
||||||
|
return tokenString, err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
package worker
|
||||||
|
|
||||||
|
import "math/rand"
|
||||||
|
|
||||||
|
func GetRandomString(l int) string {
|
||||||
|
str := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
bytes := []byte(str)
|
||||||
|
var result []byte
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
result = append(result, bytes[rand.Intn(len(bytes))])
|
||||||
|
}
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue