feat: add jwt
This commit is contained in:
@@ -9,6 +9,7 @@ type ServerConfig struct {
|
||||
LogPath string `yaml:"logPath"`
|
||||
MySQL MySQLConfig `yaml:"mysql"`
|
||||
Redis RedisConfig `yaml:"redis"`
|
||||
Jwt JwtConfig `yaml:"jwt"`
|
||||
}
|
||||
|
||||
type MySQLConfig struct {
|
||||
@@ -24,3 +25,9 @@ type RedisConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
Password string `yaml:"password"`
|
||||
}
|
||||
|
||||
type JwtConfig struct {
|
||||
Secret string `yaml:"secret"`
|
||||
RenewExpireDays uint `yaml:"renewExpireDays"`
|
||||
RenewAheadDays uint `yaml:"renewAheadDays"`
|
||||
}
|
||||
|
||||
17
handler/article.go
Normal file
17
handler/article.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nCovTrack-Backend/models"
|
||||
"nCovTrack-Backend/utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
func SaveArticleHandler(c *gin.Context) {
|
||||
var articleSave models.Article
|
||||
c.ShouldBindJSON(&articleSave)
|
||||
fmt.Println(utils.RenewToken("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDMxMDA5MDAsImlhdCI6MTY0MzQyNDkwMH0.L8qNmbHJtV8fiKKxGbkZk3DrKBPdvhie_oFooH5hGOY"))
|
||||
utils.Succ(c, map[string]string{"string": utils.GenerateToken(jwt.MapClaims{})})
|
||||
}
|
||||
@@ -6,12 +6,13 @@ import (
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/schema"
|
||||
)
|
||||
|
||||
func initMySQL() {
|
||||
mysqlConf := global.ServerSettings.MySQL
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", mysqlConf.Username, mysqlConf.Password, mysqlConf.Host, mysqlConf.Port, mysqlConf.Database)
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{NamingStrategy: schema.NamingStrategy{SingularTable: true}})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -49,10 +49,27 @@ func GinRecovery(stack bool) gin.HandlerFunc {
|
||||
}
|
||||
utils.RequestLogError(logParams...)
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
fmt.Println(err)
|
||||
fmt.Printf("\n%s\n", debug.Stack())
|
||||
fmt.Printf("\n%s\n", err)
|
||||
fmt.Printf("\n%s\n", cutStack(debug.Stack()))
|
||||
}
|
||||
}()
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func cutStack(stack []byte) string {
|
||||
stackStr := string(stack)
|
||||
line := 0
|
||||
lastLineCharIndex := 0
|
||||
for index, char := range stackStr {
|
||||
if char == '\n' {
|
||||
line++
|
||||
}
|
||||
if line == 7 {
|
||||
lastLineCharIndex = index + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Println(stackStr[lastLineCharIndex:])
|
||||
return ""
|
||||
}
|
||||
|
||||
16
models/article.go
Normal file
16
models/article.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
|
||||
type Article struct {
|
||||
ID int `gorm:"primaryKey;column:id" json:"-"` // 文章id
|
||||
CreateTime time.Time `gorm:"column:create_time" json:"createTime"` // 文章新建时间
|
||||
CreateUser string `gorm:"column:create_user" json:"createUser"` // 文章创建者id
|
||||
ModifyTime time.Time `gorm:"column:modify_time" json:"modifyTime"` // 文章最后更新时间
|
||||
ModifyUser string `gorm:"column:modify_user" json:"modifyUser"` // 文章最后更新者id
|
||||
Title string `gorm:"column:title" json:"title"` // 文章标题
|
||||
Tags string `gorm:"column:tags" json:"tags"` // 文章Tag
|
||||
Resume string `gorm:"column:resume" json:"resume"` // 文章简述
|
||||
Cover string `gorm:"column:cover" json:"cover"` // 文章封面
|
||||
Content string `gorm:"column:content" json:"content"` // 文章内容(如有需要可迁移至对象存储)
|
||||
}
|
||||
13
router/article.go
Normal file
13
router/article.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/handler"
|
||||
)
|
||||
|
||||
func articleRouter() {
|
||||
articleRouter := global.RootRouter.Group("/article")
|
||||
{
|
||||
articleRouter.POST("/save", handler.SaveArticleHandler)
|
||||
}
|
||||
}
|
||||
@@ -22,4 +22,5 @@ func BusiRouter() {
|
||||
//})
|
||||
}
|
||||
statisticRouter()
|
||||
articleRouter()
|
||||
}
|
||||
|
||||
17
service/article/article.go
Normal file
17
service/article/article.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"nCovTrack-Backend/global"
|
||||
"nCovTrack-Backend/models"
|
||||
)
|
||||
|
||||
func GetArticleList() []models.Article {
|
||||
return make([]models.Article, 0)
|
||||
}
|
||||
|
||||
func SaveArticle(article models.Article) {
|
||||
// 前端校验
|
||||
// articlea := &models.Article{Content: "#Ceshi", Cover: "https://www.baidu.com/link?url=AWfrkr2rXUGVmKuD08cYx7GwAfQw7qXy_ZczQuH9N_raTP0_eRTv4eZgsdYhtMhS8F7nVl9WfdF01byCD5DAKK&wd=&eqid=b50bb6b100004750000000056202107a", Resume: "sss", Tags: "s", Title: "title", CreateUser: "1", ModifyUser: "1", CreateTime: time.Now(), ModifyTime: time.Now()}
|
||||
tx := global.Db.Create(article)
|
||||
print(tx)
|
||||
}
|
||||
@@ -9,10 +9,15 @@ mysql:
|
||||
host: myhost.fallen-angle.com
|
||||
port: 3306
|
||||
username: root
|
||||
password: 13291004986@lm
|
||||
database: nCovTrack
|
||||
password: 13291004986
|
||||
database: ncov_track
|
||||
|
||||
redis:
|
||||
host: myhost.fallen-angle.com
|
||||
port: 6379
|
||||
password: wzl20001001
|
||||
|
||||
jwt:
|
||||
secret: bWF5YmVJYWxzb3NhbWV0b2JlZm9yZe
|
||||
renewExpireDays: 7
|
||||
renewAheadDays: 3
|
||||
|
||||
66
utils/jwt.go
Normal file
66
utils/jwt.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"nCovTrack-Backend/global"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
var JWT_KEY = []byte(global.ServerSettings.Jwt.Secret)
|
||||
|
||||
// Generate token for user
|
||||
// Return: token generated
|
||||
func GenerateToken(claims jwt.MapClaims) string {
|
||||
claims["exp"] = time.Now().Add(15 * 24 * time.Hour).Unix()
|
||||
claims["iat"] = time.Now().Unix()
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenStr, err := token.SignedString(JWT_KEY)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tokenStr
|
||||
}
|
||||
|
||||
// Renew user's token
|
||||
// tokenStr: user request token
|
||||
// Return:
|
||||
// BlankString: token is invalid or token is expired out of allowed time;
|
||||
// OldToken: token is not need to renew;
|
||||
// NewToekn: token is renew;
|
||||
func RenewToken(tokenStr string) string {
|
||||
token, err := jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) {
|
||||
return JWT_KEY, nil
|
||||
})
|
||||
|
||||
// Token is invalid
|
||||
switch err.(*jwt.ValidationError).Errors {
|
||||
case jwt.ValidationErrorSignatureInvalid:
|
||||
return ""
|
||||
case jwt.ValidationErrorIssuedAt:
|
||||
return ""
|
||||
}
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
expireAt := time.Unix(int64(claims["exp"].(float64)), 0)
|
||||
expireDuration := expireAt.Sub(time.Now())
|
||||
|
||||
// Token is out of allow expire duration
|
||||
if expireDuration.Hours() < float64(-global.ServerSettings.Jwt.RenewExpireDays*24) {
|
||||
return ""
|
||||
}
|
||||
// Token not need renew
|
||||
if expireDuration.Hours() > float64(global.ServerSettings.Jwt.RenewAheadDays*24) {
|
||||
return tokenStr
|
||||
}
|
||||
fmt.Println(expireDuration)
|
||||
|
||||
claims["exp"] = time.Now().Add(15 * 24 * time.Hour).Unix()
|
||||
token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenStr, err = token.SignedString(JWT_KEY)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return tokenStr
|
||||
}
|
||||
Reference in New Issue
Block a user