集成PostgreSQL数据库并实现用户注册登录功能
主要改动: - 集成 GORM 和 PostgreSQL 驱动 - 创建数据库配置模块 (pkg/config) - 实现数据库连接和初始化 (internal/database) - 更新用户模型支持 GORM 和 bcrypt 密码加密 - 重构用户注册和登录处理器使用数据库存储 - 删除旧的 users.json 文件存储方式 - 更新 README.md 和 CLAUDE.md 文档 技术栈: - GORM v1.31.1 - ORM框架 - PostgreSQL - 数据库 - bcrypt - 密码加密 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9540478583
commit
52d50b97aa
28
CLAUDE.md
28
CLAUDE.md
@ -55,9 +55,10 @@ func MiddlewareName() gin.HandlerFunc {
|
||||
### 模块结构
|
||||
- **main.go** - 应用程序入口点,服务器配置和路由设置
|
||||
- **internal/handlers/** - HTTP 请求处理器,全部使用 `*gin.Context` 并返回 JSON 响应
|
||||
- **internal/middleware/** - Gin 中间件链(当前:自定义日志记录器)
|
||||
- **internal/models/** - 数据模型(目录已存在,准备用于数据库模型)
|
||||
- **pkg/config/** - 配置管理(目录已存在但尚未填充)
|
||||
- **internal/middleware/** - Gin 中间件链(当前:自定义日志记录器、CORS)
|
||||
- **internal/models/** - 数据模型(用户模型、问题模型等)
|
||||
- **internal/database/** - 数据库连接和初始化
|
||||
- **pkg/config/** - 配置管理(数据库配置等)
|
||||
|
||||
## 常用命令
|
||||
|
||||
@ -106,12 +107,15 @@ go test -v ./...
|
||||
## 关键实现细节
|
||||
|
||||
- **框架**: 使用 Gin v1.11.0
|
||||
- **服务器端口**: :8080 (在 [main.go:22](main.go#L22) 中配置)
|
||||
- **ORM**: 使用 GORM v1.31.1
|
||||
- **数据库**: PostgreSQL (配置在 [pkg/config/config.go](pkg/config/config.go))
|
||||
- **服务器端口**: :8080 (在 [main.go:42](main.go#L42) 中配置)
|
||||
- **处理器签名**: 所有处理器使用 `func(c *gin.Context)` 模式
|
||||
- **JSON 响应**: 使用 `c.JSON()` 方法配合 `gin.H{}` 或结构体
|
||||
- **导入路径**: 使用模块名 `ankao` (在 go.mod 中定义)
|
||||
- **路由注册**: 路由在 [main.go](main.go) 中使用 `r.GET()`、`r.POST()` 等注册
|
||||
- **中间件**: 使用 `r.Use()` 全局应用或通过路由分组应用到特定路由
|
||||
- **密码加密**: 使用 bcrypt 加密存储用户密码
|
||||
|
||||
## 添加新功能
|
||||
|
||||
@ -125,10 +129,18 @@ go test -v ./...
|
||||
2. 使用 `r.Use(middleware.YourMiddleware())` 全局应用或应用到路由组
|
||||
|
||||
### 数据库集成
|
||||
项目已准备好进行数据库集成:
|
||||
- 在 `internal/models/` 中添加模型
|
||||
- 考虑使用 GORM 或类似的 ORM
|
||||
- 在 main.go 或单独的包中添加数据库初始化
|
||||
项目已集成 PostgreSQL 数据库:
|
||||
- **配置**: 数据库配置在 [pkg/config/config.go](pkg/config/config.go)
|
||||
- **初始化**: 数据库初始化在 [internal/database/database.go](internal/database/database.go)
|
||||
- **模型定义**: 在 `internal/models/` 中添加 GORM 模型
|
||||
- **迁移**: 使用 `DB.AutoMigrate()` 自动迁移表结构
|
||||
- **使用方式**: 通过 `database.GetDB()` 获取数据库实例
|
||||
|
||||
### 添加新的数据模型
|
||||
1. 在 `internal/models/` 中创建模型文件
|
||||
2. 定义结构体,使用 GORM 标签
|
||||
3. 在 [internal/database/database.go](internal/database/database.go) 的 `InitDB()` 中添加 `AutoMigrate`
|
||||
4. 在处理器中使用 `database.GetDB()` 进行数据库操作
|
||||
|
||||
## 前端开发规范
|
||||
|
||||
|
||||
41
README.md
41
README.md
@ -103,30 +103,35 @@ go build -o bin/server.exe main.go
|
||||
- 自定义日志中间件
|
||||
- RESTful API 结构
|
||||
- 健康检查端点
|
||||
- 用户登录系统(基于JSON文件存储)
|
||||
- 用户登录系统(基于PostgreSQL数据库)
|
||||
- 题目练习功能
|
||||
- 答题统计功能
|
||||
- React + TypeScript + Vite 前端
|
||||
- Ant Design Mobile UI组件库
|
||||
|
||||
## 用户系统
|
||||
## 数据库配置
|
||||
|
||||
用户数据存储在 [users.json](users.json) 文件中,格式如下:
|
||||
项目使用 PostgreSQL 数据库存储用户数据。
|
||||
|
||||
```json
|
||||
{
|
||||
"用户名": {
|
||||
"password": "密码",
|
||||
"avatar": "头像URL",
|
||||
"nickname": "昵称"
|
||||
}
|
||||
}
|
||||
```
|
||||
### 数据库连接信息
|
||||
|
||||
### 测试账号
|
||||
数据库配置位于 [pkg/config/config.go](pkg/config/config.go):
|
||||
- 主机: pgsql.yuchat.top
|
||||
- 端口: 5432
|
||||
- 数据库: ankao
|
||||
- 用户: postgres
|
||||
|
||||
- 用户名: `admin` / 密码: `123456`
|
||||
- 用户名: `test` / 密码: `test123`
|
||||
### 数据库表结构
|
||||
|
||||
**users 表**:
|
||||
- `id` - 主键
|
||||
- `username` - 用户名(唯一索引)
|
||||
- `password` - 密码(bcrypt加密)
|
||||
- `avatar` - 头像URL
|
||||
- `nickname` - 昵称
|
||||
- `created_at` - 创建时间
|
||||
- `updated_at` - 更新时间
|
||||
- `deleted_at` - 软删除时间
|
||||
|
||||
## 前端开发
|
||||
|
||||
@ -166,7 +171,8 @@ yarn build
|
||||
- 自定义日志中间件
|
||||
- RESTful API 结构
|
||||
- 健康检查端点
|
||||
- 用户登录和注册系统(基于JSON文件存储)
|
||||
- 用户登录和注册系统(基于PostgreSQL数据库)
|
||||
- 密码bcrypt加密存储
|
||||
- 题目练习功能
|
||||
- 答题统计功能
|
||||
|
||||
@ -183,6 +189,9 @@ yarn build
|
||||
### 后端
|
||||
- **Go** 1.25.1
|
||||
- **Gin** v1.11.0 - Web 框架
|
||||
- **GORM** v1.31.1 - ORM框架
|
||||
- **PostgreSQL** - 数据库
|
||||
- **bcrypt** - 密码加密
|
||||
|
||||
### 前端
|
||||
- **React** 18 - UI框架
|
||||
|
||||
14
go.mod
14
go.mod
@ -2,7 +2,12 @@ module ankao
|
||||
|
||||
go 1.25.1
|
||||
|
||||
require github.com/gin-gonic/gin v1.11.0
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.11.0
|
||||
golang.org/x/crypto v0.43.0
|
||||
gorm.io/driver/postgres v1.6.0
|
||||
gorm.io/gorm v1.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/bytedance/gopkg v0.1.3 // indirect
|
||||
@ -16,6 +21,12 @@ require (
|
||||
github.com/go-playground/validator/v10 v10.28.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v5 v5.7.6 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
@ -29,7 +40,6 @@ require (
|
||||
github.com/ugorji/go/codec v1.3.1 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
golang.org/x/arch v0.22.0 // indirect
|
||||
golang.org/x/crypto v0.43.0 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/net v0.46.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
|
||||
17
go.sum
17
go.sum
@ -30,6 +30,18 @@ github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7Lk
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.7.6 h1:rWQc5FwZSPX58r1OQmkuaNicxdmExaEz5A2DO2hUuTk=
|
||||
github.com/jackc/pgx/v5 v5.7.6/go.mod h1:aruU7o91Tc2q2cFp5h4uP3f6ztExVpyVv88Xl/8Vl8M=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||
@ -56,6 +68,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
@ -91,3 +104,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
|
||||
gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
|
||||
gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg=
|
||||
gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs=
|
||||
|
||||
45
internal/database/database.go
Normal file
45
internal/database/database.go
Normal file
@ -0,0 +1,45 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"ankao/internal/models"
|
||||
"ankao/pkg/config"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gorm.io/driver/postgres"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
)
|
||||
|
||||
var DB *gorm.DB
|
||||
|
||||
// InitDB 初始化数据库连接
|
||||
func InitDB() error {
|
||||
cfg := config.GetDatabaseConfig()
|
||||
dsn := cfg.GetDSN()
|
||||
|
||||
var err error
|
||||
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
|
||||
Logger: logger.Default.LogMode(logger.Info), // 开启SQL日志
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to connect to database: %w", err)
|
||||
}
|
||||
|
||||
log.Println("Database connected successfully")
|
||||
|
||||
// 自动迁移数据库表结构
|
||||
err = DB.AutoMigrate(&models.User{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to migrate database: %w", err)
|
||||
}
|
||||
|
||||
log.Println("Database migration completed")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetDB 获取数据库实例
|
||||
func GetDB() *gorm.DB {
|
||||
return DB
|
||||
}
|
||||
@ -1,49 +1,18 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"ankao/internal/database"
|
||||
"ankao/internal/models"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const usersFilePath = "users.json"
|
||||
|
||||
// loadUsers 从JSON文件加载用户数据
|
||||
func loadUsers() (models.UserData, error) {
|
||||
file, err := os.ReadFile(usersFilePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取用户文件失败: %w", err)
|
||||
}
|
||||
|
||||
var users models.UserData
|
||||
if err := json.Unmarshal(file, &users); err != nil {
|
||||
return nil, fmt.Errorf("解析用户数据失败: %w", err)
|
||||
}
|
||||
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// saveUsers 保存用户数据到JSON文件
|
||||
func saveUsers(users models.UserData) error {
|
||||
data, err := json.MarshalIndent(users, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("序列化用户数据失败: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(usersFilePath, data, 0644); err != nil {
|
||||
return fmt.Errorf("保存用户文件失败: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// generateToken 生成简单的token(实际项目应使用JWT)
|
||||
func generateToken(username string) string {
|
||||
data := fmt.Sprintf("%s:%d", username, time.Now().Unix())
|
||||
@ -64,29 +33,29 @@ func Login(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 加载用户数据
|
||||
users, err := loadUsers()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"message": "服务器错误",
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
// 从数据库查找用户
|
||||
var user models.User
|
||||
db := database.GetDB()
|
||||
result := db.Where("username = ?", req.Username).First(&user)
|
||||
|
||||
// 验证用户
|
||||
user, exists := users[req.Username]
|
||||
if !exists {
|
||||
if result.Error != nil {
|
||||
if result.Error == gorm.ErrRecordNotFound {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "用户名或密码错误",
|
||||
})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"message": "服务器错误",
|
||||
"error": result.Error.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
if user.Password != req.Password {
|
||||
if !user.CheckPassword(req.Password) {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "用户名或密码错误",
|
||||
@ -99,7 +68,7 @@ func Login(c *gin.Context) {
|
||||
|
||||
// 返回用户信息(不包含密码)
|
||||
userInfo := models.UserInfoResponse{
|
||||
Username: req.Username,
|
||||
Username: user.Username,
|
||||
Avatar: user.Avatar,
|
||||
Nickname: user.Nickname,
|
||||
}
|
||||
@ -127,15 +96,12 @@ func Register(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 加载现有用户数据
|
||||
users, err := loadUsers()
|
||||
if err != nil {
|
||||
// 如果文件不存在,创建新的用户数据
|
||||
users = make(models.UserData)
|
||||
}
|
||||
db := database.GetDB()
|
||||
|
||||
// 检查用户名是否已存在
|
||||
if _, exists := users[req.Username]; exists {
|
||||
var existingUser models.User
|
||||
result := db.Where("username = ?", req.Username).First(&existingUser)
|
||||
if result.Error == nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"success": false,
|
||||
"message": "用户名已存在",
|
||||
@ -146,7 +112,6 @@ func Register(c *gin.Context) {
|
||||
// 创建新用户
|
||||
newUser := models.User{
|
||||
Username: req.Username,
|
||||
Password: req.Password, // 实际项目应该加密存储
|
||||
Nickname: req.Nickname,
|
||||
Avatar: "https://api.dicebear.com/7.x/avataaars/svg?seed=" + req.Username, // 使用用户名生成默认头像
|
||||
}
|
||||
@ -156,11 +121,18 @@ func Register(c *gin.Context) {
|
||||
newUser.Nickname = req.Username
|
||||
}
|
||||
|
||||
// 添加新用户
|
||||
users[req.Username] = newUser
|
||||
// 加密密码
|
||||
if err := newUser.HashPassword(req.Password); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"message": "密码加密失败",
|
||||
"error": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 保存用户数据
|
||||
if err := saveUsers(users); err != nil {
|
||||
// 保存到数据库
|
||||
if err := db.Create(&newUser).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"success": false,
|
||||
"message": "注册失败",
|
||||
|
||||
@ -1,14 +1,41 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// User 用户结构
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
Avatar string `json:"avatar"`
|
||||
Nickname string `json:"nickname"`
|
||||
ID uint `gorm:"primaryKey" json:"id"`
|
||||
Username string `gorm:"uniqueIndex;not null;size:50" json:"username"`
|
||||
Password string `gorm:"not null;size:255" json:"-"` // json:"-" 表示在JSON响应中不返回密码
|
||||
Avatar string `gorm:"size:255" json:"avatar"`
|
||||
Nickname string `gorm:"size:50" json:"nickname"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||
}
|
||||
|
||||
// UserData 存储所有用户的结构
|
||||
// HashPassword 加密密码
|
||||
func (u *User) HashPassword(password string) error {
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Password = string(hashedPassword)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckPassword 验证密码
|
||||
func (u *User) CheckPassword(password string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// UserData 存储所有用户的结构(用于兼容旧的文件存储方式)
|
||||
type UserData map[string]User
|
||||
|
||||
// LoginRequest 登录请求
|
||||
|
||||
8
main.go
8
main.go
@ -1,13 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"ankao/internal/database"
|
||||
"ankao/internal/handlers"
|
||||
"ankao/internal/middleware"
|
||||
"log"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// 初始化数据库连接
|
||||
if err := database.InitDB(); err != nil {
|
||||
log.Fatal("数据库初始化失败:", err)
|
||||
}
|
||||
log.Println("数据库连接成功")
|
||||
|
||||
// 创建Gin路由器
|
||||
r := gin.Default()
|
||||
|
||||
|
||||
40
pkg/config/config.go
Normal file
40
pkg/config/config.go
Normal file
@ -0,0 +1,40 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// DatabaseConfig 数据库配置结构
|
||||
type DatabaseConfig struct {
|
||||
Host string
|
||||
Port int
|
||||
User string
|
||||
Password string
|
||||
DBName string
|
||||
SSLMode string
|
||||
}
|
||||
|
||||
// GetDatabaseConfig 获取数据库配置
|
||||
func GetDatabaseConfig() *DatabaseConfig {
|
||||
return &DatabaseConfig{
|
||||
Host: "pgsql.yuchat.top",
|
||||
Port: 5432,
|
||||
User: "postgres",
|
||||
Password: "longqi@1314",
|
||||
DBName: "ankao",
|
||||
SSLMode: "disable",
|
||||
}
|
||||
}
|
||||
|
||||
// GetDSN 返回数据库连接字符串
|
||||
func (c *DatabaseConfig) GetDSN() string {
|
||||
return fmt.Sprintf(
|
||||
"host=%s user=%s password=%s dbname=%s port=%d sslmode=%s",
|
||||
c.Host,
|
||||
c.User,
|
||||
c.Password,
|
||||
c.DBName,
|
||||
c.Port,
|
||||
c.SSLMode,
|
||||
)
|
||||
}
|
||||
12
users.json
12
users.json
@ -1,12 +0,0 @@
|
||||
{
|
||||
"admin": {
|
||||
"password": "123456",
|
||||
"avatar": "",
|
||||
"nickname": "管理员"
|
||||
},
|
||||
"test": {
|
||||
"password": "test123",
|
||||
"avatar": "",
|
||||
"nickname": "测试用户"
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user