Files
Logan.Li a01b89f942
CI / backend (push) Waiting to run
feat(auth): 记住登录 —— 刷新令牌持久化,不再在本机保存明文密码
- 后端:新增 refresh_token 模型与服务,登录签发 refresh token,支持静默续期与登出撤销
  (backend/internal/model/refresh_token.go, backend/internal/service/auth/refresh.go,
   auth_controller/auth_service/dto/router/jwt 配套改动)
- 前端:登录页改为「记住登录」(只持久化引导令牌与用户名,不落盘密码),401 自动刷新并重试原请求
  (stores/user.js, api/request.js, api/auth.js, main.js, Login.vue 配套改动)
- 部署:已在容器中验证运行(镜像构建于 2026-11-03 00:50,服务 healthy)
- 安全:仓库内无任何 .env/证书/密钥文件变更
2026-11-03 01:12:22 +08:00

63 lines
1.7 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package utils
import (
"errors"
"time"
"github.com/golang-jwt/jwt/v5"
)
// Claims JWT 声明 // Logan.Li
type Claims struct {
UserID uint `json:"user_id"`
Username string `json:"username"`
Role string `json:"role"`
jwt.RegisteredClaims
}
// AccessTokenTTL 访问令牌有效期(配合刷新令牌使用,过期后由前端静默刷新) // Logan.Li
const AccessTokenTTL = 24 * time.Hour
// AccessTokenTTLSeconds 访问令牌有效期(秒,供响应体 expires_in 使用) // Logan.Li
func AccessTokenTTLSeconds() int64 {
return int64(AccessTokenTTL / time.Second)
}
// GenerateToken 生成 JWT 令牌(HS256,24h 过期) // Logan.Li
func GenerateToken(userID uint, username, role, secret string) (string, error) {
claims := Claims{
UserID: userID,
Username: username,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(AccessTokenTTL)),
IssuedAt: jwt.NewNumericDate(time.Now()),
Issuer: "opsx-licence",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(secret))
}
// ParseToken 解析并校验 JWT 令牌 // Logan.Li
func ParseToken(tokenString, secret string) (*Claims, error) {
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
// 确保使用 HMAC 签名方法,防止算法混淆攻击 // Logan.Li
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, errors.New("非预期的签名算法")
}
return []byte(secret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("无效的令牌")
}