Enhance user authentication and authentication

Fix the modification of personal information
Fix the formatted page template
This commit is contained in:
2025-10-26 03:05:27 +08:00
parent 3e170ad526
commit c93ee377fe
22 changed files with 2728 additions and 2420 deletions

View File

@@ -26,8 +26,33 @@ func LoginPageHandler(w http.ResponseWriter, r *http.Request) {
return
}
// 获取或生成CSRF令牌
var token string
if existingToken := utils.GetCSRFTokenFromCookie(r); existingToken != "" {
// 重用现有的Cookie令牌
token = existingToken
} else {
// 生成新的CSRF令牌并设置到Cookie
newToken, err := utils.GenerateCSRFToken()
if err != nil {
http.Error(w, "生成CSRF令牌失败", http.StatusInternalServerError)
return
}
token = newToken
utils.SetCSRFToken(w, token)
}
// 准备模板数据
extraData := map[string]interface{}{
"Title": "管理员登录",
}
data := utils.GetDefaultTemplateData()
data["Title"] = "管理员登录"
data["CSRFToken"] = token
// 合并额外数据
for key, value := range extraData {
data[key] = value
}
utils.RenderTemplate(w, "login.html", data)
}
@@ -97,15 +122,8 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
return
}
// 设置JWT CookieHttpOnly安全
cookie := &http.Cookie{
Name: "admin_session",
Value: token,
Path: "/",
HttpOnly: true,
Secure: false, // 生产环境应设置为trueHTTPS
MaxAge: 24 * 60 * 60, // 24小时
}
// 设置JWT Cookie使用安全配置
cookie := utils.CreateSecureCookie("admin_session", token, utils.GetDefaultCookieMaxAge())
http.SetCookie(w, cookie)
utils.JsonResponse(w, http.StatusOK, true, "登录成功", map[string]interface{}{
@@ -132,15 +150,7 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request) {
// - 统一的Cookie清理函数确保一致性
// - 在JWT校验失败时自动调用提升安全性和用户体验
func clearInvalidJWTCookie(w http.ResponseWriter) {
cookie := &http.Cookie{
Name: "admin_session",
Value: "",
Path: "/",
HttpOnly: true,
Secure: false, // 生产环境应设置为true
MaxAge: -1, // 立即失效
Expires: time.Unix(0, 0), // 确保过期
}
cookie := utils.CreateExpiredCookie("admin_session")
http.SetCookie(w, cookie)
}
@@ -434,15 +444,8 @@ func GetCurrentAdminUserWithRefresh(w http.ResponseWriter, r *http.Request) (*JW
}
newToken, err := generateJWTToken(user)
if err == nil {
// 更新Cookie
newCookie := &http.Cookie{
Name: "admin_session",
Value: newToken,
Path: "/",
HttpOnly: true,
Secure: false, // 生产环境应设置为trueHTTPS
MaxAge: 24 * 60 * 60, // 24小时
}
// 更新Cookie(使用安全配置)
newCookie := utils.CreateSecureCookie("admin_session", newToken, utils.GetDefaultCookieMaxAge())
http.SetCookie(w, newCookie)
refreshed = true

View File

@@ -7,7 +7,8 @@ import (
"math/big"
"net/http"
"strings"
"time"
"networkDev/utils"
"github.com/mojocn/base64Captcha"
)
@@ -62,15 +63,7 @@ func CaptchaHandler(w http.ResponseWriter, r *http.Request) {
// 将验证码ID存储到session中这里简化处理实际项目中应该使用更安全的方式
// 设置cookie来存储验证码ID
cookie := &http.Cookie{
Name: "captcha_id",
Value: id,
Path: "/",
HttpOnly: true,
Secure: false, // 生产环境应设置为true
MaxAge: 300, // 5分钟过期
Expires: time.Now().Add(5 * time.Minute),
}
cookie := utils.CreateSecureCookie("captcha_id", id, 300) // 5分钟过期
http.SetCookie(w, cookie)
// 解码base64图片数据并返回

View File

@@ -26,21 +26,47 @@ func AdminIndexHandler(w http.ResponseWriter, r *http.Request) {
// AdminLayoutHandler 后台布局页渲染
// - 渲染 layout.html包含顶部导航、侧边栏与动态内容容器
func AdminLayoutHandler(w http.ResponseWriter, r *http.Request) {
data := utils.GetDefaultTemplateData()
// 获取或生成CSRF令牌
var token string
if existingToken := utils.GetCSRFTokenFromCookie(r); existingToken != "" {
// 重用现有的Cookie令牌
token = existingToken
} else {
// 生成新的CSRF令牌并设置到Cookie
newToken, err := utils.GenerateCSRFToken()
if err != nil {
http.Error(w, "生成CSRF令牌失败", http.StatusInternalServerError)
return
}
token = newToken
utils.SetCSRFToken(w, token)
}
// 准备额外的模板数据
extraData := make(map[string]interface{})
// 从数据库读取站点标题
db, err := database.GetDB()
if err != nil {
data["Title"] = "凌动技术"
db, dbErr := database.GetDB()
if dbErr != nil {
extraData["Title"] = "凌动技术"
} else {
siteTitle, err := services.FindSettingByName("site_title", db)
if err != nil || siteTitle == nil {
data["Title"] = "凌动技术"
siteTitle, settingErr := services.FindSettingByName("site_title", db)
if settingErr != nil || siteTitle == nil {
extraData["Title"] = "凌动技术"
} else {
data["Title"] = siteTitle.Value
extraData["Title"] = siteTitle.Value
}
}
// 准备模板数据
data := utils.GetDefaultTemplateData()
data["CSRFToken"] = token
// 合并额外数据
for key, value := range extraData {
data[key] = value
}
utils.RenderTemplate(w, "layout.html", data)
}

View File

@@ -160,15 +160,8 @@ func UserPasswordUpdateHandler(w http.ResponseWriter, r *http.Request) {
return
}
// 更新Cookie
cookie := &http.Cookie{
Name: "admin_session",
Value: newToken,
Path: "/",
HttpOnly: true,
Secure: false, // 生产环境应设置为trueHTTPS
MaxAge: 24 * 60 * 60, // 24小时
}
// 更新Cookie(使用安全配置)
cookie := utils.CreateSecureCookie("admin_session", newToken, utils.GetDefaultCookieMaxAge())
http.SetCookie(w, cookie)
// 密码修改成功已重新生成JWT令牌
@@ -260,20 +253,14 @@ func UserProfileUpdateHandler(w http.ResponseWriter, r *http.Request) {
}
// 重新签发JWT并写入Cookie
newUser := models.User{UUID: claims.UserUUID, Username: username, Role: claims.Role}
token, err := generateJWTToken(newUser)
// 使用完整的用户信息包含密码来生成JWT令牌
user.Username = username // 更新用户名
token, err := generateJWTToken(user)
if err != nil {
utils.JsonResponse(w, http.StatusInternalServerError, false, "生成新令牌失败", nil)
return
}
cookie := &http.Cookie{
Name: "admin_session",
Value: token,
Path: "/",
HttpOnly: true,
Secure: false,
MaxAge: 24 * 60 * 60,
}
cookie := utils.CreateSecureCookie("admin_session", token, utils.GetDefaultCookieMaxAge())
http.SetCookie(w, cookie)
utils.JsonResponse(w, http.StatusOK, true, "保存成功", map[string]interface{}{