up
This commit is contained in:
@@ -18,10 +18,8 @@ database:
|
||||
|
||||
user:
|
||||
cookieTimeout: 604800
|
||||
passHashType: "md5" #密码哈希类型 text md5
|
||||
avatarSavePath: "/data/avatar/" #头像保存的真实位置
|
||||
avatarGinrouterPath: "/avatar/" #gin 路由的路径
|
||||
avatarPath: "/static/avatars/def.png"
|
||||
passHashType: "md5" #密码哈希类型 text md5 md5salt
|
||||
|
||||
|
||||
file:
|
||||
maxSize: 52428800
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
"apiErr":-1,
|
||||
"postErr":-2,
|
||||
"jsonErr":-3,
|
||||
"userNameDup":-4
|
||||
"userNameDup":-4,
|
||||
"userNameNoFund":-41,
|
||||
"userPassIncorrect":-42
|
||||
|
||||
}
|
||||
@@ -15,11 +15,8 @@ type ConfigsWeb_ struct {
|
||||
}
|
||||
|
||||
type ConfigsUser_ struct {
|
||||
CookieTimeout int `mapstructure:"cookieTimeout"`
|
||||
PassHashType string `mapstructure:"passHashType"`
|
||||
AvatarSavePath string `mapstructure:"avatarSavePath"`
|
||||
AvatarGinrouterPath string `mapstructure:"avatarGinrouterPath"`
|
||||
AvatarPath string `mapstructure:"avatarPath"`
|
||||
CookieTimeout int `mapstructure:"cookieTimeout"`
|
||||
PassHashType string `mapstructure:"passHashType"`
|
||||
}
|
||||
|
||||
type ConfigsFile_ struct {
|
||||
|
||||
+10
-4
@@ -39,13 +39,19 @@ func Md5Str(str string) string {
|
||||
return hashString2
|
||||
}
|
||||
|
||||
func HashUserPass(str string) string {
|
||||
func HashUserPass(user *TabUser_) {
|
||||
switch ConfigsUser.PassHashType {
|
||||
case "text":
|
||||
return str
|
||||
break
|
||||
case "md5":
|
||||
return Md5Str(str)
|
||||
user.Pass = Md5Str(user.Pass)
|
||||
|
||||
case "md5salt":
|
||||
if user.Salt == "" {
|
||||
user.Salt = RandStr32()
|
||||
}
|
||||
user.Pass = Md5Str(Md5Str(user.Pass) + user.Salt)
|
||||
|
||||
}
|
||||
|
||||
return GetCurrentTimeString() + RandStr32() //如果转换失败返回当前时间,避免撞库
|
||||
}
|
||||
|
||||
+43
-10
@@ -1,17 +1,50 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
type APIRequestLog struct {
|
||||
ID int64 `gorm:"primaryKey;column:id" json:"id"`
|
||||
IPAddress string `gorm:"column:ip_address;size:45;not null" json:"ip_address"`
|
||||
Path string `gorm:"column:path;size:500;not null" json:"path"`
|
||||
Method string `gorm:"column:method;size:10;not null" json:"method"`
|
||||
StatusCode int `gorm:"column:status_code;index" json:"status_code"`
|
||||
Message string `gorm:"column:error_message;type:text" json:"error_message"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// GetRealIP 获取真实IP(处理代理)
|
||||
func GetRealIP(c *gin.Context) string {
|
||||
// 优先级顺序
|
||||
headers := []string{
|
||||
"CF-Connecting-IP", // Cloudflare
|
||||
"True-Client-IP",
|
||||
"X-Forwarded-For",
|
||||
"X-Real-IP",
|
||||
}
|
||||
|
||||
for _, header := range headers {
|
||||
if ip := c.GetHeader(header); ip != "" {
|
||||
// 处理多个IP的情况(如 X-Forwarded-For: client, proxy1, proxy2)
|
||||
if strings.Contains(ip, ",") {
|
||||
ips := strings.Split(ip, ",")
|
||||
ip = strings.TrimSpace(ips[0])
|
||||
}
|
||||
|
||||
if net.ParseIP(ip) != nil {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 最后使用Gin的ClientIP方法
|
||||
return c.ClientIP()
|
||||
}
|
||||
|
||||
func LogAdd() {
|
||||
func LogAdd(c *gin.Context, msg string) {
|
||||
|
||||
var logtemp APIRequestLog_
|
||||
|
||||
logtemp.IPAddress = GetRealIP(c)
|
||||
logtemp.Path = c.Request.URL.Path
|
||||
logtemp.Method = c.Request.Method
|
||||
logtemp.Message = msg
|
||||
|
||||
//fmt.Println(logtemp)
|
||||
DB.Create(&logtemp)
|
||||
|
||||
}
|
||||
|
||||
+26
-18
@@ -25,11 +25,12 @@ type TabFileInfo_ struct {
|
||||
}
|
||||
|
||||
type TabUser_ struct {
|
||||
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
|
||||
Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引
|
||||
Email string `gorm:"size:255;index"` // 字符串长度限制100 索引
|
||||
Pass string `gorm:"size:128"` // 建议存储哈希后的密码
|
||||
Type string `gorm:"size:64;default:user"` //
|
||||
ID uint `gorm:"primaryKey;autoIncrement"` // 自增主键
|
||||
Name string `gorm:"size:100;uniqueIndex"` // 唯一约束索引
|
||||
Email string `gorm:"size:255;index"` // 字符串长度限制100 索引
|
||||
Pass string `gorm:"size:128"` // 建议存储哈希后的密码
|
||||
Type string `gorm:"size:64;default:user"` //
|
||||
Salt string `gorm:"size:64;"`
|
||||
Date time.Time `gorm:"type:datetime;default:CURRENT_TIMESTAMP"` // 默认当前时间
|
||||
}
|
||||
|
||||
@@ -67,19 +68,24 @@ type TabUserInfo_ struct {
|
||||
// }
|
||||
|
||||
type TabCookie_ struct {
|
||||
ID uint `gorm:"primaryKey;autoIncrement"`
|
||||
UserID uint `gorm:"size:16;not null"`
|
||||
Name string `gorm:"size:255;not null;index"`
|
||||
Value string `gorm:"size:255;not null;index"`
|
||||
Domain string `gorm:"size:255;not null"`
|
||||
Path string `gorm:"size:255;not null;default:/"`
|
||||
ExpiresAt time.Time `gorm:"type:datetime;index"`
|
||||
CreatedAt time.Time `gorm:"type:datetime;not null;default:CURRENT_TIMESTAMP"`
|
||||
UpdatedAt time.Time `gorm:"type:datetime;index;not null;default:CURRENT_TIMESTAMP"`
|
||||
SecureFlag bool `gorm:"not null;default:false"`
|
||||
HttpOnly bool `gorm:"not null;default:false"`
|
||||
SameSite string `gorm:"size:10;not null;default:'Lax'"`
|
||||
PartitionKey string `gorm:"size:50"`
|
||||
ID uint `gorm:"primaryKey;autoIncrement"`
|
||||
UserID uint `gorm:"size:16;not null"`
|
||||
Name string `gorm:"size:255;not null;index"`
|
||||
Value string `gorm:"size:255;not null;index"`
|
||||
ExpiresAt time.Time `gorm:"type:datetime;index"`
|
||||
CreatedAt time.Time `gorm:"type:datetime;not null;default:CURRENT_TIMESTAMP"`
|
||||
UpdatedAt time.Time `gorm:"type:datetime;index;not null;default:CURRENT_TIMESTAMP"`
|
||||
Remember bool `gorm:"default:false"`
|
||||
}
|
||||
|
||||
type APIRequestLog_ struct {
|
||||
ID int64 `gorm:"primaryKey;column:id" json:"id"`
|
||||
IPAddress string `gorm:"column:ip_address;size:45;not null" json:"ip_address"`
|
||||
Path string `gorm:"column:path;size:500;not null" json:"path"`
|
||||
Method string `gorm:"column:method;size:10;not null" json:"method"`
|
||||
StatusCode int `gorm:"column:status_code;index" json:"status_code"`
|
||||
Message string `gorm:"column:error_message;type:text" json:"error_message"`
|
||||
CreatedAt time.Time `gorm:"column:created_at;type:datetime;default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||
}
|
||||
|
||||
func DatabaseInit() error {
|
||||
@@ -115,5 +121,7 @@ func DatabaseInit() error {
|
||||
|
||||
DB.AutoMigrate(&TabFileInfo_{})
|
||||
|
||||
DB.AutoMigrate(&APIRequestLog_{})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package routers
|
||||
import (
|
||||
"fmt"
|
||||
"ops/models"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -20,8 +21,12 @@ func ApiInit() {
|
||||
if models.DB.Where(&user).First(&user).Error == nil {
|
||||
|
||||
} else {
|
||||
fmt.Println("用户不存在")
|
||||
user.Pass = models.HashUserPass("adminpassword")
|
||||
//fmt.Println("用户不存在")
|
||||
|
||||
//对密码加盐
|
||||
user.Salt = models.RandStr32()
|
||||
user.Pass = "adminpassword"
|
||||
models.HashUserPass(&user)
|
||||
models.DB.Create(&user) // 传入指针
|
||||
}
|
||||
|
||||
@@ -54,6 +59,12 @@ type From_user_add struct {
|
||||
Userpass string `json:"userpass"`
|
||||
}
|
||||
|
||||
type From_user_login struct {
|
||||
Username string `json:"username"`
|
||||
Userpass string `json:"userpass"`
|
||||
Remember bool `json:"remember"`
|
||||
}
|
||||
|
||||
func ApiUser(r *gin.RouterGroup) {
|
||||
|
||||
r.GET("/test", func(ctx *gin.Context) {
|
||||
@@ -62,6 +73,67 @@ func ApiUser(r *gin.RouterGroup) {
|
||||
r.POST("/test", func(ctx *gin.Context) {
|
||||
ReturnJson(ctx, "apiOK", nil)
|
||||
})
|
||||
//用户登陆
|
||||
r.POST("/login", func(ctx *gin.Context) {
|
||||
var loginuser From_user_login
|
||||
data, _ := SeparateData(ctx)
|
||||
if data != nil {
|
||||
if err := mapstructure.Decode(data, &loginuser); err == nil {
|
||||
if loginuser.Username != "" && loginuser.Userpass != "" {
|
||||
//传入的数据都ok,获取用户信息
|
||||
|
||||
getuser := models.TabUser_{
|
||||
Name: loginuser.Username,
|
||||
}
|
||||
|
||||
if models.DB.Where(&getuser).First(&getuser).Error == nil {
|
||||
//倒入数据
|
||||
user := models.TabUser_{
|
||||
Pass: loginuser.Userpass, //密码明文
|
||||
Salt: getuser.Salt, //保存的盐制
|
||||
}
|
||||
//哈希密
|
||||
models.HashUserPass(&user)
|
||||
if user.Pass == getuser.Pass {
|
||||
//用户密码正确,生成cookie
|
||||
cookie := models.TabCookie_{
|
||||
UserID: getuser.ID,
|
||||
Name: "login",
|
||||
Value: models.RandStr32(),
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
ExpiresAt: time.Now().Add(time.Duration(models.ConfigsUser.CookieTimeout) * time.Second), //计算过期时间,
|
||||
Remember: loginuser.Remember,
|
||||
}
|
||||
models.DB.Create(&cookie) // 传入指针
|
||||
|
||||
redata := map[string]interface{}{
|
||||
"cookie": cookie,
|
||||
}
|
||||
|
||||
ReturnJson(ctx, "apiOK", redata)
|
||||
} else {
|
||||
ReturnJson(ctx, "userPassIncorrect", nil)
|
||||
}
|
||||
|
||||
} else {
|
||||
//用户不存在
|
||||
ReturnJson(ctx, "userNameNoFund", nil)
|
||||
}
|
||||
|
||||
} else {
|
||||
ReturnJson(ctx, "jsonErr", nil)
|
||||
}
|
||||
} else {
|
||||
ReturnJson(ctx, "jsonErr", nil)
|
||||
}
|
||||
|
||||
} else {
|
||||
ReturnJson(ctx, "postErr", nil)
|
||||
}
|
||||
})
|
||||
|
||||
//用户注册
|
||||
r.POST("/register", func(ctx *gin.Context) {
|
||||
//转换传进来的数据
|
||||
var jsonData From_user_add
|
||||
@@ -79,8 +151,7 @@ func ApiUser(r *gin.RouterGroup) {
|
||||
// Date 字段无需赋值,数据库会自动填充默认值
|
||||
}
|
||||
if newUser.Name != "" && newUser.Pass != "" && newUser.Email != "" {
|
||||
//对用户的密码进行哈希替换
|
||||
newUser.Pass = models.HashUserPass(newUser.Pass)
|
||||
|
||||
//用户名是唯一的,先读取是否有这个用户名
|
||||
var user models.TabUser_
|
||||
user.Name = newUser.Name
|
||||
@@ -90,13 +161,18 @@ func ApiUser(r *gin.RouterGroup) {
|
||||
ReturnJson(ctx, "userNameDup", nil)
|
||||
} else {
|
||||
//fmt.Println("用户不存在")
|
||||
|
||||
//对密码加盐
|
||||
newUser.Salt = models.RandStr32()
|
||||
|
||||
//对用户的密码进行哈希替换
|
||||
models.HashUserPass(&newUser)
|
||||
|
||||
models.DB.Create(&newUser) // 传入指针
|
||||
|
||||
// //创建info
|
||||
// var user_info models.TabUserInfo_
|
||||
// user_info.AvatarPath = models.ConfigsUser.AvatarPath
|
||||
// user_info.UserID = newUser.ID
|
||||
// models.DB.Create(&user_info) // 传入指针
|
||||
//创建用户后写一个log
|
||||
|
||||
models.LogAdd(ctx, "New user id:"+strconv.Itoa(int(newUser.ID)))
|
||||
|
||||
ReturnJson(ctx, "apiOK", nil)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user