206 lines
6.4 KiB
Go
206 lines
6.4 KiB
Go
package main
|
||
|
||
import (
|
||
"database/sql"
|
||
"fmt"
|
||
"log"
|
||
"net/http"
|
||
"os"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
_ "github.com/lib/pq"
|
||
"golang.org/x/crypto/bcrypt"
|
||
)
|
||
|
||
// UpdatePasswordRequest 更新密码请求参数结构
|
||
type UpdatePasswordRequest struct {
|
||
UserID string `json:"user_id" binding:"required"`
|
||
OldPassword string `json:"old_password" binding:"required"`
|
||
NewPassword string `json:"new_password" binding:"required,min=6"`
|
||
}
|
||
|
||
// UpdatePasswordResponse 更新密码响应结构
|
||
type UpdatePasswordResponse struct {
|
||
Success bool `json:"success"`
|
||
Message string `json:"message"`
|
||
}
|
||
|
||
var db *sql.DB
|
||
|
||
func main() {
|
||
// 初始化日志输出格式
|
||
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
|
||
log.Println("开始初始化应用程序")
|
||
|
||
// 初始化Gin引擎
|
||
r := gin.Default()
|
||
log.Println("Gin引擎初始化完成")
|
||
|
||
// 从环境变量获取数据库配置
|
||
dbHost := os.Getenv("DB_HOST")
|
||
dbPort := os.Getenv("DB_PORT")
|
||
dbUser := os.Getenv("DB_USER")
|
||
dbPassword := os.Getenv("DB_PASSWORD")
|
||
dbName := os.Getenv("DB_NAME")
|
||
log.Printf("读取数据库配置: host=%s, port=%s, user=%s, dbname=%s", dbHost, dbPort, dbUser, dbName)
|
||
|
||
// 构建数据库连接字符串
|
||
connStr := fmt.Sprintf(
|
||
"host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
|
||
dbHost, dbPort, dbUser, dbPassword, dbName,
|
||
)
|
||
|
||
var err error
|
||
db, err = sql.Open("postgres", connStr)
|
||
if err != nil {
|
||
log.Panicf("无法连接数据库: %v", err)
|
||
}
|
||
defer db.Close()
|
||
log.Println("数据库连接对象创建成功")
|
||
|
||
// 验证数据库连接
|
||
if err := db.Ping(); err != nil {
|
||
log.Panicf("数据库连接失败: %v", err)
|
||
}
|
||
log.Println("数据库连接验证成功")
|
||
|
||
// 更新密码接口
|
||
r.POST("/user/update/password", updatePasswordHandler)
|
||
log.Println("注册更新密码接口: POST /user/update/password")
|
||
|
||
// 启动服务,监听80端口
|
||
log.Println("服务启动在80端口")
|
||
if err := r.Run(":80"); err != nil {
|
||
log.Panicf("服务启动失败: %v", err)
|
||
}
|
||
}
|
||
|
||
// updatePasswordHandler 处理密码更新逻辑
|
||
func updatePasswordHandler(c *gin.Context) {
|
||
requestID := c.Request.Header.Get("X-Request-ID")
|
||
if requestID == "" {
|
||
requestID = fmt.Sprintf("req-%d", gin.Mode())
|
||
}
|
||
log.Printf("[%s] 收到更新密码请求 from %s", requestID, c.ClientIP())
|
||
|
||
var req UpdatePasswordRequest
|
||
// 绑定并验证请求参数
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
log.Printf("[%s] 请求参数绑定失败: %v", requestID, err)
|
||
c.JSON(http.StatusBadRequest, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "请求参数错误: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
log.Printf("[%s] 请求参数验证通过, 用户ID: %s", requestID, req.UserID)
|
||
|
||
// 1. 检查新旧密码是否一致
|
||
if req.OldPassword == req.NewPassword {
|
||
log.Printf("[%s] 新密码与旧密码相同, 用户ID: %s", requestID, req.UserID)
|
||
c.JSON(http.StatusOK, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "新密码不能与旧密码相同",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 2. 对旧密码进行加密处理
|
||
log.Printf("[%s] 开始对旧密码进行加密, 用户ID: %s", requestID, req.UserID)
|
||
hashedOldPassword, err := bcrypt.GenerateFromPassword([]byte(req.OldPassword), bcrypt.DefaultCost)
|
||
if err != nil {
|
||
log.Printf("[%s] 旧密码加密失败: %v, 用户ID: %s", requestID, err, req.UserID)
|
||
c.JSON(http.StatusInternalServerError, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "旧密码加密失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
log.Printf("[%s] 旧密码加密完成, 用户ID: %s", requestID, req.UserID)
|
||
|
||
// 3. 使用加密后的旧密码查询并验证(按user_id匹配)
|
||
var count int
|
||
query := `
|
||
SELECT COUNT(*) FROM user_password
|
||
WHERE user_id = $1 AND password = $2
|
||
`
|
||
log.Printf("[%s] 执行旧密码验证查询, SQL: %s, 参数: [%s, ****]", requestID, query, req.UserID)
|
||
err = db.QueryRow(query, req.UserID, string(hashedOldPassword)).Scan(&count)
|
||
if err != nil {
|
||
log.Printf("[%s] 旧密码验证查询失败: %v, 用户ID: %s", requestID, err, req.UserID)
|
||
c.JSON(http.StatusInternalServerError, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "验证旧密码失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 验证失败处理
|
||
if count == 0 {
|
||
log.Printf("[%s] 旧密码验证失败, 用户ID: %s", requestID, req.UserID)
|
||
c.JSON(http.StatusOK, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "旧密码不正确",
|
||
})
|
||
return
|
||
}
|
||
log.Printf("[%s] 旧密码验证成功, 用户ID: %s", requestID, req.UserID)
|
||
|
||
// 4. 对新密码进行加密处理
|
||
log.Printf("[%s] 开始对新密码进行加密, 用户ID: %s", requestID, req.UserID)
|
||
hashedNewPassword, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
|
||
if err != nil {
|
||
log.Printf("[%s] 新密码加密失败: %v, 用户ID: %s", requestID, err, req.UserID)
|
||
c.JSON(http.StatusInternalServerError, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "新密码加密失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
log.Printf("[%s] 新密码加密完成, 用户ID: %s", requestID, req.UserID)
|
||
|
||
// 5. 更新密码表中的密码(按user_id匹配)
|
||
updateQuery := `
|
||
UPDATE user_password
|
||
SET password = $1
|
||
WHERE user_id = $2
|
||
`
|
||
log.Printf("[%s] 执行密码更新, SQL: %s, 参数: [****, %s]", requestID, updateQuery, req.UserID)
|
||
result, err := db.Exec(updateQuery, string(hashedNewPassword), req.UserID)
|
||
if err != nil {
|
||
log.Printf("[%s] 密码更新执行失败: %v, 用户ID: %s", requestID, err, req.UserID)
|
||
c.JSON(http.StatusInternalServerError, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "更新密码失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 6. 检查更新结果
|
||
rowsAffected, err := result.RowsAffected()
|
||
if err != nil {
|
||
log.Printf("[%s] 获取更新行数失败: %v, 用户ID: %s", requestID, err, req.UserID)
|
||
c.JSON(http.StatusInternalServerError, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "检查更新结果失败: " + err.Error(),
|
||
})
|
||
return
|
||
}
|
||
log.Printf("[%s] 密码更新影响行数: %d, 用户ID: %s", requestID, rowsAffected, req.UserID)
|
||
|
||
if rowsAffected == 0 {
|
||
log.Printf("[%s] 未找到用户或密码未变化, 用户ID: %s", requestID, req.UserID)
|
||
c.JSON(http.StatusOK, UpdatePasswordResponse{
|
||
Success: false,
|
||
Message: "未找到用户或密码未发生变化",
|
||
})
|
||
return
|
||
}
|
||
|
||
// 7. 更新成功
|
||
log.Printf("[%s] 密码更新成功, 用户ID: %s", requestID, req.UserID)
|
||
c.JSON(http.StatusOK, UpdatePasswordResponse{
|
||
Success: true,
|
||
Message: "密码更新成功",
|
||
})
|
||
} |