mirror of
https://github.com/skyle1995/NetworkAuth.git
synced 2026-05-25 02:24:05 +08:00
Fix the authentication mechanism
Fix filter search
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -19,9 +18,10 @@ import (
|
||||
// LoginPageHandler 管理员登录页渲染处理器
|
||||
// - 如果已登录则重定向到 /admin
|
||||
// - 否则渲染 web/template/admin/login.html 模板
|
||||
// - 自动清理失效的JWT Cookie,避免刷新时的问题
|
||||
func LoginPageHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 已登录直接跳转到后台布局
|
||||
if IsAdminAuthenticated(r) {
|
||||
// 使用带清理功能的JWT校验,避免失效Cookie在登录页面造成问题
|
||||
if IsAdminAuthenticatedWithCleanup(w, r) {
|
||||
http.Redirect(w, r, "/admin", http.StatusFound)
|
||||
return
|
||||
}
|
||||
@@ -118,6 +118,20 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// - 确保令牌完全失效
|
||||
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 清理JWT Cookie
|
||||
clearInvalidJWTCookie(w)
|
||||
|
||||
// 可选:将JWT令牌加入黑名单(需要Redis或数据库支持)
|
||||
// 这里可以实现JWT黑名单机制
|
||||
|
||||
utils.JsonResponse(w, http.StatusOK, true, "已退出登录", map[string]interface{}{
|
||||
"redirect": "/admin/login",
|
||||
})
|
||||
}
|
||||
|
||||
// clearInvalidJWTCookie 清理失效的JWT Cookie
|
||||
// - 统一的Cookie清理函数,确保一致性
|
||||
// - 在JWT校验失败时自动调用,提升安全性和用户体验
|
||||
func clearInvalidJWTCookie(w http.ResponseWriter) {
|
||||
cookie := &http.Cookie{
|
||||
Name: "admin_session",
|
||||
Value: "",
|
||||
@@ -128,13 +142,6 @@ func LogoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
Expires: time.Unix(0, 0), // 确保过期
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
|
||||
// 可选:将JWT令牌加入黑名单(需要Redis或数据库支持)
|
||||
// 这里可以实现JWT黑名单机制
|
||||
|
||||
utils.JsonResponse(w, http.StatusOK, true, "已退出登录", map[string]interface{}{
|
||||
"redirect": "/admin/login",
|
||||
})
|
||||
}
|
||||
|
||||
// JWT密钥(生产环境应从配置文件或环境变量读取)
|
||||
@@ -142,9 +149,10 @@ var jwtSecret = []byte(viper.GetString("security.jwt_secret"))
|
||||
|
||||
// JWTClaims JWT载荷结构
|
||||
type JWTClaims struct {
|
||||
UserID uint `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
Role int `json:"role"`
|
||||
UserUUID string `json:"user_uuid"`
|
||||
Username string `json:"username"`
|
||||
Role int `json:"role"`
|
||||
PasswordHash string `json:"password_hash"` // 密码哈希摘要,用于验证密码是否被修改
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
@@ -153,16 +161,20 @@ type JWTClaims struct {
|
||||
// - 设置24小时过期时间
|
||||
// - 使用HMAC-SHA256签名
|
||||
func generateJWTToken(user models.User) (string, error) {
|
||||
// 生成密码哈希摘要(使用SHA256)
|
||||
passwordHashDigest := utils.GenerateSHA256Hash(user.Password)
|
||||
|
||||
claims := JWTClaims{
|
||||
UserID: user.ID,
|
||||
Username: user.Username,
|
||||
Role: user.Role,
|
||||
UserUUID: user.UUID,
|
||||
Username: user.Username,
|
||||
Role: user.Role,
|
||||
PasswordHash: passwordHashDigest, // 包含密码哈希摘要
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
Issuer: "凌动技术",
|
||||
Subject: strconv.Itoa(int(user.ID)),
|
||||
Subject: user.UUID,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -213,8 +225,96 @@ func IsAdminAuthenticated(r *http.Request) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 可选:进一步验证用户是否仍然存在且有效
|
||||
// 这里可以添加数据库查询来验证用户状态
|
||||
// 验证用户是否仍然存在于数据库中
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if dbErr := db.Where("uuid = ? AND role = 0", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
// 记录安全事件:用户不存在但持有有效JWT令牌
|
||||
fmt.Printf("[SECURITY WARNING] Invalid JWT token detected - User not found: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证用户名是否匹配(防止用户名被修改后仍使用旧令牌)
|
||||
if user.Username != claims.Username {
|
||||
// 记录安全事件:用户名不匹配
|
||||
fmt.Printf("[SECURITY WARNING] Username mismatch detected - Token username=%s, DB username=%s, UUID=%s, IP=%s\n",
|
||||
claims.Username, user.Username, claims.UserUUID, r.RemoteAddr)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证密码哈希是否匹配(防止密码被修改后仍使用旧令牌)
|
||||
currentPasswordHash := utils.GenerateSHA256Hash(user.Password)
|
||||
if claims.PasswordHash != currentPasswordHash {
|
||||
// 记录安全事件:密码哈希不匹配,可能密码已被修改
|
||||
fmt.Printf("[SECURITY WARNING] Password hash mismatch detected - Token may be invalid due to password change: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// IsAdminAuthenticatedWithCleanup 带自动清理功能的JWT校验函数
|
||||
// - 当JWT校验失败时,自动清理失效的Cookie
|
||||
// - 适用于API接口等需要清理失效令牌的场景
|
||||
func IsAdminAuthenticatedWithCleanup(w http.ResponseWriter, r *http.Request) bool {
|
||||
cookie, err := r.Cookie("admin_session")
|
||||
if err != nil || cookie.Value == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// 解析并验证JWT令牌
|
||||
claims, err := parseJWTToken(cookie.Value)
|
||||
if err != nil {
|
||||
// JWT解析失败,清理失效Cookie
|
||||
clearInvalidJWTCookie(w)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证用户角色(只允许管理员角色=0)
|
||||
if claims.Role != 0 {
|
||||
clearInvalidJWTCookie(w)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证用户是否仍然存在于数据库中
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if dbErr := db.Where("uuid = ? AND role = 0", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
// 记录安全事件并清理失效Cookie
|
||||
fmt.Printf("[SECURITY WARNING] Invalid JWT token detected - User not found: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
clearInvalidJWTCookie(w)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证用户名是否匹配(防止用户名被修改后仍使用旧令牌)
|
||||
if user.Username != claims.Username {
|
||||
// 记录安全事件并清理失效Cookie
|
||||
fmt.Printf("[SECURITY WARNING] Username mismatch detected - Token username=%s, DB username=%s, UUID=%s, IP=%s\n",
|
||||
claims.Username, user.Username, claims.UserUUID, r.RemoteAddr)
|
||||
clearInvalidJWTCookie(w)
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证密码哈希是否匹配(防止密码被修改后仍使用旧令牌)
|
||||
currentPasswordHash := utils.GenerateSHA256Hash(user.Password)
|
||||
if claims.PasswordHash != currentPasswordHash {
|
||||
// 记录安全事件并清理失效Cookie
|
||||
fmt.Printf("[SECURITY WARNING] Password hash mismatch detected - Token may be invalid due to password change: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
clearInvalidJWTCookie(w)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -238,6 +338,37 @@ func GetCurrentAdminUser(r *http.Request) (*JWTClaims, error) {
|
||||
return nil, fmt.Errorf("权限不足")
|
||||
}
|
||||
|
||||
// 验证用户是否仍然存在于数据库中
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("数据库连接失败")
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if dbErr := db.Where("uuid = ? AND role = 0", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
// 记录安全事件:用户不存在但持有有效JWT令牌
|
||||
fmt.Printf("[SECURITY WARNING] Invalid JWT token detected in GetCurrentAdminUser - User not found: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
return nil, fmt.Errorf("用户不存在或权限已变更")
|
||||
}
|
||||
|
||||
// 验证用户名是否匹配(防止用户名被修改后仍使用旧令牌)
|
||||
if user.Username != claims.Username {
|
||||
// 记录安全事件:用户名不匹配
|
||||
fmt.Printf("[SECURITY WARNING] Username mismatch detected in GetCurrentAdminUser - Token username=%s, DB username=%s, UUID=%s, IP=%s\n",
|
||||
claims.Username, user.Username, claims.UserUUID, r.RemoteAddr)
|
||||
return nil, fmt.Errorf("用户信息已变更,请重新登录")
|
||||
}
|
||||
|
||||
// 验证密码哈希是否匹配(防止密码被修改后仍使用旧令牌)
|
||||
currentPasswordHash := utils.GenerateSHA256Hash(user.Password)
|
||||
if claims.PasswordHash != currentPasswordHash {
|
||||
// 记录安全事件:密码哈希不匹配,可能密码已被修改
|
||||
fmt.Printf("[SECURITY WARNING] Password hash mismatch detected in GetCurrentAdminUser - Token may be invalid due to password change: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
return nil, fmt.Errorf("密码已变更,请重新登录")
|
||||
}
|
||||
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
@@ -260,13 +391,44 @@ func GetCurrentAdminUserWithRefresh(w http.ResponseWriter, r *http.Request) (*JW
|
||||
return nil, false, fmt.Errorf("权限不足")
|
||||
}
|
||||
|
||||
// 验证用户是否仍然存在于数据库中
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("数据库连接失败")
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if dbErr := db.Where("uuid = ? AND role = 0", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
// 记录安全事件:用户不存在但持有有效JWT令牌
|
||||
fmt.Printf("[SECURITY WARNING] Invalid JWT token detected in GetCurrentAdminUserWithRefresh - User not found: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
return nil, false, fmt.Errorf("用户不存在或权限已变更")
|
||||
}
|
||||
|
||||
// 验证用户名是否匹配(防止用户名被修改后仍使用旧令牌)
|
||||
if user.Username != claims.Username {
|
||||
// 记录安全事件:用户名不匹配
|
||||
fmt.Printf("[SECURITY WARNING] Username mismatch detected in GetCurrentAdminUserWithRefresh - Token username=%s, DB username=%s, UUID=%s, IP=%s\n",
|
||||
claims.Username, user.Username, claims.UserUUID, r.RemoteAddr)
|
||||
return nil, false, fmt.Errorf("用户信息已变更,请重新登录")
|
||||
}
|
||||
|
||||
// 验证密码哈希是否匹配(防止密码被修改后仍使用旧令牌)
|
||||
currentPasswordHash := utils.GenerateSHA256Hash(user.Password)
|
||||
if claims.PasswordHash != currentPasswordHash {
|
||||
// 记录安全事件:密码哈希不匹配,可能密码已被修改
|
||||
fmt.Printf("[SECURITY WARNING] Password hash mismatch detected in GetCurrentAdminUserWithRefresh - Token may be invalid due to password change: UUID=%s, Username=%s, IP=%s\n",
|
||||
claims.UserUUID, claims.Username, r.RemoteAddr)
|
||||
return nil, false, fmt.Errorf("密码已变更,请重新登录")
|
||||
}
|
||||
|
||||
// 检查是否需要刷新令牌(根据配置的阈值)
|
||||
refreshed := false
|
||||
refreshThreshold := time.Duration(viper.GetInt("security.jwt_refresh_threshold_hours")) * time.Hour
|
||||
if time.Until(claims.ExpiresAt.Time) < refreshThreshold {
|
||||
// 生成新的JWT令牌
|
||||
user := models.User{
|
||||
ID: claims.UserID,
|
||||
UUID: claims.UserUUID,
|
||||
Username: claims.Username,
|
||||
Role: claims.Role,
|
||||
}
|
||||
@@ -301,6 +463,9 @@ func AdminAuthRequired(next http.HandlerFunc) http.HandlerFunc {
|
||||
// 尝试获取用户信息并自动刷新令牌
|
||||
claims, refreshed, err := GetCurrentAdminUserWithRefresh(w, r)
|
||||
if err != nil {
|
||||
// 自动清理失效的JWT Cookie,提升安全性和用户体验
|
||||
clearInvalidJWTCookie(w)
|
||||
|
||||
// 中文注释:区分普通页面请求与AJAX/JSON请求
|
||||
// - 对 AJAX/JSON:直接返回 401 JSON,便于前端处理(如提示重新登录)
|
||||
// - 对普通页面:保持原有重定向到登录页
|
||||
|
||||
@@ -13,8 +13,9 @@ import (
|
||||
// AdminIndexHandler /admin 与 /admin/ 根路径入口
|
||||
// - 未登录:重定向到 /admin/login
|
||||
// - 已登录:渲染后台布局页(或重定向到 /admin/layout)
|
||||
// - 自动清理失效的JWT Cookie
|
||||
func AdminIndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if IsAdminAuthenticated(r) {
|
||||
if IsAdminAuthenticatedWithCleanup(w, r) {
|
||||
// 直接渲染布局页,保持URL为 /admin
|
||||
AdminLayoutHandler(w, r)
|
||||
return
|
||||
|
||||
@@ -2,6 +2,7 @@ package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"networkDev/database"
|
||||
"networkDev/models"
|
||||
@@ -16,7 +17,7 @@ func UserFragmentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// UserProfileQueryHandler 查询当前登录管理员的基本信息
|
||||
// - 返回 id/username/role 三个字段
|
||||
// - 返回 uuid/username/role/created_at 四个字段
|
||||
// - 自动刷新接近过期的JWT令牌
|
||||
func UserProfileQueryHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
@@ -30,10 +31,24 @@ func UserProfileQueryHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// 查询用户完整信息以获取创建时间
|
||||
db, err := database.GetDB()
|
||||
if err != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "数据库连接失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
var user models.User
|
||||
if dbErr := db.Where("uuid = ?", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusNotFound, false, "用户不存在", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.JsonResponse(w, http.StatusOK, true, "ok", map[string]interface{}{
|
||||
"id": claims.UserID,
|
||||
"username": claims.Username,
|
||||
"role": claims.Role,
|
||||
"uuid": user.UUID,
|
||||
"username": user.Username,
|
||||
"role": user.Role,
|
||||
"created_at": user.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -91,7 +106,7 @@ func UserPasswordUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 查询当前用户
|
||||
var user models.User
|
||||
if dbErr := db.First(&user, claims.UserID).Error; dbErr != nil {
|
||||
if dbErr := db.Where("uuid = ?", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusNotFound, false, "用户不存在", nil)
|
||||
return
|
||||
}
|
||||
@@ -105,30 +120,59 @@ func UserPasswordUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 生成新的密码盐值
|
||||
newSalt, err := utils.GenerateRandomSalt()
|
||||
if err != nil {
|
||||
// 添加详细错误日志
|
||||
fmt.Printf("生成密码盐失败: %v\n", err)
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "生成密码盐失败", nil)
|
||||
return
|
||||
}
|
||||
fmt.Printf("成功生成新盐值,长度: %d\n", len(newSalt))
|
||||
|
||||
// 使用新盐值生成密码哈希
|
||||
hash, err := utils.HashPasswordWithSalt(body.NewPassword, newSalt)
|
||||
if err != nil {
|
||||
// 添加详细错误日志
|
||||
fmt.Printf("生成密码哈希失败: %v, 密码长度: %d, 盐值长度: %d\n", err, len(body.NewPassword), len(newSalt))
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "生成密码哈希失败", nil)
|
||||
return
|
||||
}
|
||||
fmt.Printf("成功生成密码哈希,长度: %d\n", len(hash))
|
||||
|
||||
// 更新密码和盐值
|
||||
if err := db.Model(&models.User{}).Where("id = ?", claims.UserID).Updates(map[string]interface{}{
|
||||
if dbErr := db.Model(&models.User{}).Where("uuid = ?", claims.UserUUID).Updates(map[string]interface{}{
|
||||
"password": hash,
|
||||
"password_salt": newSalt,
|
||||
}).Error; err != nil {
|
||||
}).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "更新密码失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// 可选:安全起见,通知前端跳转到登录页
|
||||
utils.JsonResponse(w, http.StatusOK, true, "密码修改成功,请重新登录", map[string]interface{}{
|
||||
"redirect": "/admin/login",
|
||||
})
|
||||
// 重新查询用户信息(包含新密码)
|
||||
var updatedUser models.User
|
||||
if dbErr := db.Where("uuid = ?", claims.UserUUID).First(&updatedUser).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "查询用户信息失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// 重新生成JWT令牌(包含新的密码哈希摘要)
|
||||
newToken, err := generateJWTToken(updatedUser)
|
||||
if err != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "生成新令牌失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// 更新Cookie
|
||||
cookie := &http.Cookie{
|
||||
Name: "admin_session",
|
||||
Value: newToken,
|
||||
Path: "/",
|
||||
HttpOnly: true,
|
||||
Secure: false, // 生产环境应设置为true(HTTPS)
|
||||
MaxAge: 24 * 60 * 60, // 24小时
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
|
||||
// 密码修改成功,已重新生成JWT令牌
|
||||
utils.JsonResponse(w, http.StatusOK, true, "密码修改成功", nil)
|
||||
}
|
||||
|
||||
// UserProfileUpdateHandler 修改当前登录管理员的用户名
|
||||
@@ -173,9 +217,9 @@ func UserProfileUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// 检查唯一性:排除当前用户ID
|
||||
// 检查唯一性:排除当前用户UUID
|
||||
var cnt int64
|
||||
if dbErr := db.Model(&models.User{}).Where("username = ? AND id <> ?", username, claims.UserID).Count(&cnt).Error; dbErr != nil {
|
||||
if dbErr := db.Model(&models.User{}).Where("username = ? AND uuid <> ?", username, claims.UserUUID).Count(&cnt).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "检查用户名唯一性失败", nil)
|
||||
return
|
||||
}
|
||||
@@ -199,7 +243,7 @@ func UserProfileUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
// 查询当前用户并校验旧密码
|
||||
var user models.User
|
||||
if dbErr := db.First(&user, claims.UserID).Error; dbErr != nil {
|
||||
if dbErr := db.Where("uuid = ?", claims.UserUUID).First(&user).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusNotFound, false, "用户不存在", nil)
|
||||
return
|
||||
}
|
||||
@@ -210,13 +254,13 @@ func UserProfileUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// 执行更新
|
||||
if dbErr := db.Model(&models.User{}).Where("id = ?", claims.UserID).Update("username", username).Error; dbErr != nil {
|
||||
if dbErr := db.Model(&models.User{}).Where("uuid = ?", claims.UserUUID).Update("username", username).Error; dbErr != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "更新用户名失败", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// 重新签发JWT并写入Cookie
|
||||
newUser := models.User{ID: claims.UserID, Username: username, Role: claims.Role}
|
||||
newUser := models.User{UUID: claims.UserUUID, Username: username, Role: claims.Role}
|
||||
token, err := generateJWTToken(newUser)
|
||||
if err != nil {
|
||||
utils.JsonResponse(w, http.StatusInternalServerError, false, "生成新令牌失败", nil)
|
||||
|
||||
@@ -40,8 +40,13 @@ func VariableListHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 获取应用UUID参数(用于按应用筛选变量)
|
||||
appUUID := strings.TrimSpace(r.URL.Query().Get("app_uuid"))
|
||||
|
||||
// 获取别名搜索参数
|
||||
alias := strings.TrimSpace(r.URL.Query().Get("alias"))
|
||||
// 获取搜索关键词参数(支持编号、别名、数据的综合搜索)
|
||||
search := strings.TrimSpace(r.URL.Query().Get("search"))
|
||||
|
||||
// 兼容旧的别名搜索参数
|
||||
if search == "" {
|
||||
search = strings.TrimSpace(r.URL.Query().Get("alias"))
|
||||
}
|
||||
|
||||
// 构建查询
|
||||
db, err := database.GetDB()
|
||||
@@ -59,9 +64,10 @@ func VariableListHandler(w http.ResponseWriter, r *http.Request) {
|
||||
query = query.Where("app_uuid = ?", appUUID)
|
||||
}
|
||||
|
||||
// 如果指定了别名搜索,则按别名模糊搜索
|
||||
if alias != "" {
|
||||
query = query.Where("alias LIKE ?", "%"+alias+"%")
|
||||
// 如果指定了搜索关键词,则在编号、别名、数据、备注中进行模糊搜索
|
||||
if search != "" {
|
||||
query = query.Where("number LIKE ? OR alias LIKE ? OR data LIKE ? OR remark LIKE ?",
|
||||
"%"+search+"%", "%"+search+"%", "%"+search+"%", "%"+search+"%")
|
||||
}
|
||||
|
||||
// 获取总数
|
||||
|
||||
Reference in New Issue
Block a user