init code
This commit is contained in:
162
api_login/main.go
Normal file
162
api_login/main.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/lib/pq"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// LoginRequest 登录请求参数结构
|
||||
type LoginRequest struct {
|
||||
Account string `json:"account" binding:"required"`
|
||||
Password string `json:"password" binding:"required"`
|
||||
}
|
||||
|
||||
// LoginResponse 登录响应结构
|
||||
type LoginResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Data struct {
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
} `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
var db *sql.DB
|
||||
|
||||
func main() {
|
||||
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,
|
||||
)
|
||||
log.Printf("数据库连接字符串构建完成: %s", connStr)
|
||||
|
||||
var err error
|
||||
db, err = sql.Open("postgres", connStr)
|
||||
if err != nil {
|
||||
log.Fatalf("无法连接数据库: %v", err)
|
||||
panic(fmt.Sprintf("无法连接数据库: %v", err))
|
||||
}
|
||||
defer db.Close()
|
||||
log.Println("数据库连接对象创建成功")
|
||||
|
||||
// 验证数据库连接
|
||||
if err := db.Ping(); err != nil {
|
||||
log.Fatalf("数据库连接失败: %v", err)
|
||||
panic(fmt.Sprintf("数据库连接失败: %v", err))
|
||||
}
|
||||
log.Println("数据库连接验证成功")
|
||||
|
||||
// 登录接口
|
||||
r.POST("/user/login", loginHandler)
|
||||
log.Println("登录接口注册完成: POST /user/login")
|
||||
|
||||
// 启动服务,监听80端口
|
||||
log.Println("服务启动在80端口")
|
||||
r.Run(":80")
|
||||
}
|
||||
|
||||
// loginHandler 处理登录逻辑
|
||||
func loginHandler(c *gin.Context) {
|
||||
reqID := c.Request.Header.Get("X-Request-ID")
|
||||
if reqID == "" {
|
||||
reqID = fmt.Sprintf("%d", gin.Mode()) // 简单生成一个请求标识
|
||||
}
|
||||
log.Printf("[%s] 收到登录请求 from %s", reqID, c.ClientIP())
|
||||
|
||||
var req LoginRequest
|
||||
// 绑定并验证请求参数
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
log.Printf("[%s] 请求参数绑定失败: %v, 请求体: %+v", reqID, err, c.Request.Body)
|
||||
c.JSON(http.StatusBadRequest, LoginResponse{
|
||||
Success: false,
|
||||
Message: "账号或密码不能为空",
|
||||
})
|
||||
return
|
||||
}
|
||||
log.Printf("[%s] 请求参数绑定成功: 账号=%s", reqID, req.Account)
|
||||
|
||||
// 1. 判断账号和密码是否为空(双重保险)
|
||||
if req.Account == "" || req.Password == "" {
|
||||
log.Printf("[%s] 账号或密码为空: 账号=%s", reqID, req.Account)
|
||||
c.JSON(http.StatusBadRequest, LoginResponse{
|
||||
Success: false,
|
||||
Message: "账号或密码不能为空",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 查询账号对应的密码和用户ID
|
||||
var storedPassword string
|
||||
var userID string
|
||||
query := `
|
||||
SELECT password, user_id
|
||||
FROM user_account_password_view
|
||||
WHERE account = $1 AND deleted = false
|
||||
`
|
||||
log.Printf("[%s] 执行查询: %s, 参数: %s", reqID, query, req.Account)
|
||||
err := db.QueryRow(query, req.Account).Scan(&storedPassword, &userID)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
// 账号不存在或已被删除
|
||||
log.Printf("[%s] 账号不存在或已删除: %s", reqID, req.Account)
|
||||
c.JSON(http.StatusOK, LoginResponse{
|
||||
Success: false,
|
||||
Message: "账号不存在",
|
||||
})
|
||||
return
|
||||
case err != nil:
|
||||
log.Printf("[%s] 查询账号信息失败: %v, 账号=%s", reqID, err, req.Account)
|
||||
c.JSON(http.StatusInternalServerError, LoginResponse{
|
||||
Success: false,
|
||||
Message: "查询账号信息失败",
|
||||
})
|
||||
return
|
||||
}
|
||||
log.Printf("[%s] 查询账号信息成功: 账号=%s, userID=%s", reqID, req.Account, userID)
|
||||
|
||||
// 3. 验证密码(使用bcrypt比较原始密码和存储的加密密码)
|
||||
err = bcrypt.CompareHashAndPassword([]byte(storedPassword), []byte(req.Password))
|
||||
if err != nil {
|
||||
// 密码不匹配
|
||||
log.Printf("[%s] 密码验证失败: 账号=%s, 错误=%v", reqID, req.Account, err)
|
||||
c.JSON(http.StatusOK, LoginResponse{
|
||||
Success: false,
|
||||
Message: "密码错误",
|
||||
})
|
||||
return
|
||||
}
|
||||
log.Printf("[%s] 密码验证成功: 账号=%s", reqID, req.Account)
|
||||
|
||||
// 4. 登录成功
|
||||
log.Printf("[%s] 登录成功: 账号=%s, userID=%s", reqID, req.Account, userID)
|
||||
c.JSON(http.StatusOK, LoginResponse{
|
||||
Success: true,
|
||||
Message: "登录成功",
|
||||
Data: struct {
|
||||
UserID string `json:"user_id,omitempty"`
|
||||
}{
|
||||
UserID: userID,
|
||||
},
|
||||
})
|
||||
}
|
Reference in New Issue
Block a user