feat(bookmark): 初始化书签服务并配置路由与权限控制
新增书签服务主程序,使用 Gin 框架搭建 HTTP 服务器,并注册书签相关接口处理器。 配置 CORS 中间件以支持跨域请求。服务监听端口为 8081。 feat(user_np): 初始化用户权限服务并注册认证接口 新增用户权限服务主程序,使用 Gin 框架搭建 HTTP 服务器,并注册登录、注册及修改密码等接口处理器。 服务监听端口为 8082。 refactor(config): 重构 OpenAPI 配置文件结构并拆分模块 将原有合并的 OpenAPI 配置文件按功能模块拆分为 bookmark 和 user_np 两个独立目录, 分别管理各自的 server、client 及 API 定义文件,便于后续维护和扩展。 refactor(vfs): 调整虚拟文件系统 API 接口路径与参数定义 更新 VFS API 配置文件,修改部分接口路径及参数结构, 如将文件路径参数由 path 转为 query 参数,并优化响应结构体定义。
This commit is contained in:
100
internal/models/user_np.go
Normal file
100
internal/models/user_np.go
Normal file
@ -0,0 +1,100 @@
|
||||
// internal/models/user_np.go
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// UserNP 用户名密码认证模型
|
||||
type UserNP struct {
|
||||
ID int64 `json:"id" gorm:"primaryKey"`
|
||||
Username string `json:"username" gorm:"not null;index;size:255;unique"`
|
||||
Password string `json:"password" gorm:"not null;size:255"`
|
||||
Email *string `json:"email" gorm:"type:text;unique"`
|
||||
Token *string `json:"token" gorm:"type:text"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"autoCreateTime"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"autoUpdateTime"`
|
||||
DeletedAt gorm.DeletedAt `json:"deleted_at" gorm:"index"`
|
||||
}
|
||||
|
||||
// JWTSecret JWT签名密钥(在实际应用中应该从环境变量或配置文件中读取)
|
||||
var JWTSecret = []byte("your-secret-key-change-in-production")
|
||||
|
||||
// SimpleClaims 简单的JWT声明结构体
|
||||
type SimpleClaims struct {
|
||||
Username string `json:"username"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// HashPassword 对密码进行哈希处理
|
||||
func (u *UserNP) HashPassword(password string) error {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
u.Password = string(bytes)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CheckPassword 验证密码
|
||||
func (u *UserNP) CheckPassword(providedPassword string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(providedPassword))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// GenerateSimpleJWT 生成简单的JWT Token
|
||||
func (u *UserNP) GenerateSimpleJWT() (string, error) {
|
||||
expirationTime := time.Now().Add(24 * time.Hour)
|
||||
|
||||
claims := &SimpleClaims{
|
||||
Username: u.Username,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
Issuer: "zzyxyz_user_np_api",
|
||||
Subject: u.Username,
|
||||
ID: string(rune(u.ID)), // 将用户ID作为JWT ID
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString(JWTSecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return tokenString, nil
|
||||
}
|
||||
|
||||
// CheckSimpleJWT 验证JWT Token
|
||||
func CheckSimpleJWT(tokenString string) (string, error) {
|
||||
claims := &SimpleClaims{}
|
||||
|
||||
// 解析token
|
||||
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
|
||||
return JWTSecret, nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
// 检查是否是token过期错误
|
||||
if errors.Is(err, jwt.ErrTokenExpired) {
|
||||
return "", errors.New("token已过期")
|
||||
}
|
||||
return "", errors.New("无效的token")
|
||||
}
|
||||
|
||||
// 验证token有效性
|
||||
if !token.Valid {
|
||||
return "", errors.New("无效的token")
|
||||
}
|
||||
|
||||
// 返回用户名
|
||||
return claims.Username, nil
|
||||
}
|
Reference in New Issue
Block a user