jdysya d989b0e7cb refactor(gateway): 优化 URL 处理逻辑
- 移除了 PostLogin 中的 URL 解码步骤,直接使用 returnURL
- 在 StaticAuthMiddleware 中增加了 URL 解码,以确保准确匹配受保护 URL
- 优化了错误处理,提高了代码的健壮性
2025-02-16 22:02:47 +08:00

200 lines
4.8 KiB
Go

package handlers
import (
"net/http"
"strconv"
"strings"
"gateway/config"
"gateway/models"
"gateway/utils"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"github.com/jinzhu/gorm"
"golang.org/x/crypto/bcrypt"
)
func GetLogin(c *gin.Context) {
returnURL := c.Query("return_url")
c.HTML(http.StatusOK, "login.html", gin.H{
"return_url": returnURL,
})
}
func PostLogin(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
username := c.PostForm("username")
password := c.PostForm("password")
returnURL := c.PostForm("return_url")
var user models.User
if err := db.Where("mobile = ?", username).First(&user).Error; err != nil {
c.HTML(http.StatusUnauthorized, "login.html", gin.H{
"error": "用户不存在或密码错误",
"return_url": returnURL,
})
return
}
if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)); err != nil {
c.HTML(http.StatusUnauthorized, "login.html", gin.H{
"error": "用户不存在或密码错误",
"return_url": returnURL,
})
return
}
session := sessions.Default(c)
session.Set("user", user.ID)
if err := session.Save(); err != nil {
utils.Logger.Errorf("Session保存失败: %v", err)
c.HTML(http.StatusInternalServerError, "login.html", gin.H{
"error": "登录状态保存失败",
"return_url": returnURL,
})
return
}
if returnURL != "" {
c.Redirect(http.StatusSeeOther, returnURL)
return
}
c.Redirect(http.StatusSeeOther, "/")
}
}
func GetRegister(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
regions, err := getRegions(db)
if err != nil {
c.HTML(http.StatusInternalServerError, "register.html", gin.H{"error": "系统错误"})
return
}
c.HTML(http.StatusOK, "register.html", gin.H{"regions": regions})
}
}
func PostRegister(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
regionStr, exists := c.GetPostForm("region")
if !exists {
handleRegisterError(c, db, "请选择所在地区")
return
}
regionID, err := strconv.ParseUint(regionStr, 10, 32)
if err != nil {
handleRegisterError(c, db, "无效的地区参数")
return
}
user := models.User{
FullName: c.PostForm("fullname"),
Mobile: c.PostForm("mobile"),
RegionID: uint(regionID),
}
var region models.Region
if err := db.First(&region, user.RegionID).Error; err != nil {
handleRegisterError(c, db, "请选择有效地区")
return
}
if len(user.Mobile) != 11 {
handleRegisterError(c, db, "手机号格式不正确")
return
}
password := c.PostForm("password")
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
utils.Logger.Errorf("密码加密失败: %v", err)
handleRegisterError(c, db, "注册失败")
return
}
user.Password = string(hashedPassword)
if err := db.Create(&user).Error; err != nil {
utils.Logger.Errorf("用户创建失败: %v", err)
errorMsg := "注册失败"
if strings.Contains(err.Error(), "UNIQUE constraint failed") {
errorMsg = "该手机号已注册"
}
handleRegisterError(c, db, errorMsg)
return
}
c.Redirect(http.StatusSeeOther, "/login")
}
}
func Logout(c *gin.Context) {
session := sessions.Default(c)
// 使用配置中的session选项
session.Options(config.GetLogoutSessionOptions())
// 清除session数据
session.Clear()
// 保存更改
if err := session.Save(); err != nil {
utils.Logger.Errorf("退出登录失败: %v", err)
c.HTML(http.StatusInternalServerError, "error.html", gin.H{"error": "退出登录失败"})
return
}
c.Redirect(http.StatusSeeOther, "/login")
}
func getRegions(db *gorm.DB) ([]models.Region, error) {
var regions []models.Region
if err := db.Find(&regions).Error; err != nil {
utils.Logger.Errorf("获取地区数据失败: %v", err)
return nil, err
}
return regions, nil
}
func handleRegisterError(c *gin.Context, db *gorm.DB, errorMessage string) {
regions, err := getRegions(db)
if err != nil {
c.HTML(http.StatusInternalServerError, "register.html", gin.H{"error": "系统错误"})
return
}
c.HTML(http.StatusBadRequest, "register.html", gin.H{
"error": errorMessage,
"regions": regions,
"form": gin.H{
"fullname": c.PostForm("fullname"),
"mobile": c.PostForm("mobile"),
},
})
}
func GetUserInfo(db *gorm.DB) gin.HandlerFunc {
return func(c *gin.Context) {
session := sessions.Default(c)
userID := session.Get("user")
if userID == nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "未登录"})
return
}
var user models.User
if err := db.First(&user, userID).Error; err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取用户信息失败"})
return
}
c.JSON(http.StatusOK, gin.H{
"id": user.ID,
"fullName": user.FullName,
"mobile": user.Mobile,
})
}
}