This commit is contained in:
2025-05-03 08:05:02 +08:00
parent e19385b3d0
commit 86e8ea4baa
12 changed files with 293 additions and 0 deletions

View File

93
config/config.go Normal file
View File

@ -0,0 +1,93 @@
package config
import (
"errors"
"fmt"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
var (
ServerPort string
Mode string
JwtSecret string
//MessageSavingDays = 30 // 消息在数据库保存时间,单位天
//MessageHangingSeconds = 10 // 消息挂起时间,单位秒
//MessageResponseTimeout = 60 // 长轮询消息响应超时时间,单位秒
// CommitHash 构件时注入的git commit hash
CommitHash = "develop" // git commit hash 构建时注入
BuildTime = "0000-00-00 00:00:00" // 构建时间
)
func init() {
// 设置配置文件路径
viper.AddConfigPath(".")
viper.SetConfigName("config")
viper.SetConfigType("yaml")
// 读取配置文件
if err := viper.ReadInConfig(); err != nil {
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
panic(fmt.Errorf("Fatal error config file: %s \n", err))
}
}
// 初始化配置常量
ServerPort = GetString("server.port", "8888")
JwtSecret = GetString("jwtSecret", "none-secret")
logrus.Info("配置初始化成功")
}
func Get[T any](key string, defaultValue T) T {
if !viper.IsSet(key) {
return defaultValue
}
value := viper.Get(key)
if v, ok := value.(T); ok {
return v
}
return defaultValue
}
// GetString 返回配置项的字符串值
func GetString(key string, defaultValue ...string) string {
if len(defaultValue) > 0 {
return Get(key, defaultValue[0])
}
return viper.GetString(key)
}
// GetInt 返回配置项的整数值
func GetInt(key string, defaultValue ...int) int {
if len(defaultValue) > 0 {
return Get(key, defaultValue[0])
}
return viper.GetInt(key)
}
// GetBool 返回配置项的布尔值
func GetBool(key string, defaultValue ...bool) bool {
if len(defaultValue) > 0 {
return Get(key, defaultValue[0])
}
return viper.GetBool(key)
}
// GetFloat64 返回配置项的浮点数值
func GetFloat64(key string, defaultValue ...float64) float64 {
if len(defaultValue) > 0 {
return Get(key, defaultValue[0])
}
return viper.GetFloat64(key)
}
// GetStringSlice 返回配置项的字符串切片值
func GetStringSlice(key string, defaultValue ...[]string) []string {
if len(defaultValue) > 0 {
return Get(key, defaultValue[0])
}
return viper.GetStringSlice(key)
}

20
middle/auth.go Normal file
View File

@ -0,0 +1,20 @@
package middle
import (
"context"
"github.com/LiteyukiStudio/spage/resps"
"github.com/cloudwego/hertz/pkg/app"
)
type Auth struct{}
func (Auth) AuthToken() func(context.Context, *app.RequestContext) {
return func(ctx context.Context, c *app.RequestContext) {
token := string(c.GetHeader("Authorization"))
if token == "" {
resps.BadRequest(c, "Token is required")
c.Abort()
return
}
}
}

View File

@ -0,0 +1 @@
package models

49
resps/resps.go Normal file
View File

@ -0,0 +1,49 @@
package resps
import "github.com/cloudwego/hertz/pkg/app"
func Custom(c *app.RequestContext, code int, message string, data ...map[string]any) {
if len(data) == 0 {
data = append(data, map[string]any{})
}
data[0]["message"] = message
c.JSON(code, data[0])
}
// 2xx
func Ok(c *app.RequestContext, message string, data ...map[string]any) {
if len(data) == 0 {
data = append(data, map[string]any{})
}
data[0]["message"] = message
c.JSON(200, data[0])
}
// 4xx
func BadRequest(c *app.RequestContext, message string) {
c.JSON(400, map[string]string{"message": message})
}
func Unauthorized(c *app.RequestContext, message string) {
c.JSON(401, map[string]string{"message": message})
}
func Forbidden(c *app.RequestContext, message string, err error) {
c.JSON(403, map[string]string{"message": message})
}
func NotFound(c *app.RequestContext, message string) {
c.JSON(404, map[string]string{"message": message})
}
// 5xx
func InternalServerError(c *app.RequestContext, message string) {
c.JSON(500, map[string]string{"message": message})
}
func ServiceUnavailable(c *app.RequestContext, message string) {
c.JSON(503, map[string]string{"message": message})
}

View File

@ -0,0 +1,36 @@
package router
import (
"context"
"github.com/LiteyukiStudio/spage/config"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/app/server"
"github.com/cloudwego/hertz/pkg/common/utils"
)
//var H *server.Hertz
func Run() error {
// 运行路由
H := server.New(server.WithHostPorts(":" + config.ServerPort))
H.GET("/", func(ctx context.Context, c *app.RequestContext) {
c.JSON(200, utils.H{"message": "Hello World"})
})
apiV1 := H.Group("/api/v1")
{
userGroup := apiV1.Group("/user")
_ = userGroup
}
// 运行服务
if config.Mode == "dev" {
err := H.Run()
if err != nil {
return err
}
} else {
H.Spin()
}
return nil
}

View File

@ -0,0 +1 @@
package rpc

View File

@ -0,0 +1 @@
package store

6
utils/auth/auth.go Normal file
View File

@ -0,0 +1,6 @@
package auth
type UtilsType struct {
}
var Auth = UtilsType{}

32
utils/auth/password.go Normal file
View File

@ -0,0 +1,32 @@
package auth
import (
"crypto/sha256"
"encoding/hex"
"golang.org/x/crypto/bcrypt"
)
// HashPassword 密码哈希函数
func (u *UtilsType) HashPassword(password string, salt string) (string, error) {
saltedPassword := Auth.addSalt(password, salt)
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(saltedPassword), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedPassword), nil
}
// VerifyPassword 验证密码
func (u *UtilsType) VerifyPassword(password string, hash string, salt string) bool {
saltedPassword := Auth.addSalt(password, salt)
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(saltedPassword))
return err == nil
}
// addSalt 加盐函数
func (u *UtilsType) addSalt(password string, salt string) string {
combined := password + salt
hash := sha256.New()
hash.Write([]byte(combined))
return hex.EncodeToString(hash.Sum(nil))
}

51
utils/auth/token.go Normal file
View File

@ -0,0 +1,51 @@
package auth
import (
"github.com/LiteyukiStudio/spage/config"
"github.com/golang-jwt/jwt/v5"
"time"
)
// TokenSecret is the secret key used to sign the JWT tokens
var TokenSecret = config.JwtSecret
// Claims defines the structure of JWT claims
type Claims struct {
jwt.RegisteredClaims
UserID uint `json:"user_id"`
}
// GenerateToken 为用户生成指定有效期的Token
func (u *UtilsType) GenerateToken(userID uint, expireDuration time.Duration) (string, error) {
claims := Claims{
UserID: userID,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(expireDuration)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
}
// 创建一个新的token对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 签名token
tokenString, err := token.SignedString([]byte(TokenSecret))
if err != nil {
return "", err
}
return tokenString, nil
}
// ValidateToken 验证token
func (u *UtilsType) ValidateToken(tokenString string) (*Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (any, error) {
return []byte(TokenSecret), nil
})
if err != nil {
return nil, err
}
if !token.Valid {
return nil, jwt.ErrSignatureInvalid
}
return claims, nil
}

3
utils/init.go Normal file
View File

@ -0,0 +1,3 @@
package utils
type Utils struct{}