feat: ToNav-go v1.0.0 - 内部服务导航系统
功能: - 前台导航: 分类Tab切换、实时搜索、健康状态指示、响应式适配 - 后台管理: 服务/分类CRUD、系统设置、登录认证(bcrypt) - 健康检查: 定时检测(5min)、独立检查URL、三态指示(在线/离线/未检测) - 云端备份: WebDAV上传/下载/恢复/删除、定时自动备份、本地备份管理 技术栈: Go + Gin + GORM + SQLite
This commit is contained in:
121
handlers/auth.go
Normal file
121
handlers/auth.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"tonav-go/database"
|
||||
"tonav-go/models"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-gonic/gin"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
// LoginHandler 处理登录请求
|
||||
func LoginHandler(c *gin.Context) {
|
||||
var input struct {
|
||||
Username string `form:"username" binding:"required"`
|
||||
Password string `form:"password" binding:"required"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBind(&input); err != nil {
|
||||
c.HTML(http.StatusOK, "login.html", gin.H{"error": "用户名和密码不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if err := database.DB.Where("username = ?", input.Username).First(&user).Error; err != nil {
|
||||
c.HTML(http.StatusOK, "login.html", gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(input.Password)); err != nil {
|
||||
c.HTML(http.StatusOK, "login.html", gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
session := sessions.Default(c)
|
||||
session.Set("user_id", int(user.ID))
|
||||
session.Set("username", user.Username)
|
||||
session.Set("must_change", user.MustChangePassword)
|
||||
if err := session.Save(); err != nil {
|
||||
log.Printf("Session save error: %v", err)
|
||||
c.HTML(http.StatusOK, "login.html", gin.H{"error": "登录失败,请重试"})
|
||||
return
|
||||
}
|
||||
|
||||
if user.MustChangePassword {
|
||||
c.Redirect(http.StatusFound, "/admin/change-password")
|
||||
return
|
||||
}
|
||||
c.Redirect(http.StatusFound, "/admin/dashboard")
|
||||
}
|
||||
|
||||
// LogoutHandler 处理退出登录
|
||||
func LogoutHandler(c *gin.Context) {
|
||||
session := sessions.Default(c)
|
||||
session.Clear()
|
||||
session.Save()
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
}
|
||||
|
||||
// ChangePasswordHandler 修改密码
|
||||
func ChangePasswordHandler(c *gin.Context) {
|
||||
if c.Request.Method == "GET" {
|
||||
c.HTML(http.StatusOK, "change_password.html", nil)
|
||||
return
|
||||
}
|
||||
|
||||
var input struct {
|
||||
OldPassword string `form:"old_password" binding:"required"`
|
||||
NewPassword string `form:"new_password" binding:"required"`
|
||||
ConfirmPassword string `form:"confirm_password" binding:"required"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBind(&input); err != nil {
|
||||
c.HTML(http.StatusOK, "change_password.html", gin.H{"error": "所有字段均为必填"})
|
||||
return
|
||||
}
|
||||
|
||||
if input.NewPassword != input.ConfirmPassword {
|
||||
c.HTML(http.StatusOK, "change_password.html", gin.H{"error": "两次输入的新密码不一致"})
|
||||
return
|
||||
}
|
||||
|
||||
if len(input.NewPassword) < 6 {
|
||||
c.HTML(http.StatusOK, "change_password.html", gin.H{"error": "新密码长度不能少于6位"})
|
||||
return
|
||||
}
|
||||
|
||||
session := sessions.Default(c)
|
||||
userID, err := getSessionUserID(session)
|
||||
if err != nil {
|
||||
c.Redirect(http.StatusFound, "/admin/login")
|
||||
return
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if err := database.DB.First(&user, userID).Error; err != nil {
|
||||
c.HTML(http.StatusOK, "change_password.html", gin.H{"error": "用户不存在"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(input.OldPassword)); err != nil {
|
||||
c.HTML(http.StatusOK, "change_password.html", gin.H{"error": "旧密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(input.NewPassword), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
c.HTML(http.StatusOK, "change_password.html", gin.H{"error": "密码加密失败"})
|
||||
return
|
||||
}
|
||||
user.Password = string(hashedPassword)
|
||||
user.MustChangePassword = false
|
||||
database.DB.Save(&user)
|
||||
|
||||
session.Set("must_change", false)
|
||||
session.Save()
|
||||
|
||||
c.Redirect(http.StatusFound, "/admin/dashboard")
|
||||
}
|
||||
Reference in New Issue
Block a user