Feat: Add JWT config, auth middleware, and token parsing using username.
Signed-off-by: Goldbro233 <bowensun_06@outlook.com>
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
config/config.yml
|
||||||
|
|
||||||
|
/.idea/
|
||||||
|
/qodana.yaml
|
||||||
@@ -22,6 +22,9 @@ type Config struct {
|
|||||||
Bcrypt struct {
|
Bcrypt struct {
|
||||||
Cost int
|
Cost int
|
||||||
}
|
}
|
||||||
|
Jwtconfig struct {
|
||||||
|
Secret string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var AppConfig *Config
|
var AppConfig *Config
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"GinTutorial/models"
|
"GinTutorial/models"
|
||||||
"GinTutorial/utils"
|
"GinTutorial/utils"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@@ -44,7 +43,7 @@ func Register(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := utils.GenerateJWT(strconv.Itoa(int(user.ID)))
|
token, err := utils.GenerateJWT(user.Username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusInternalServerError, gin.H{
|
ctx.JSON(http.StatusInternalServerError, gin.H{
|
||||||
@@ -87,7 +86,7 @@ func Login(ctx *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := utils.GenerateJWT(strconv.Itoa(int(user.ID)))
|
token, err := utils.GenerateJWT(user.Username)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.JSON(http.StatusInternalServerError, gin.H{
|
ctx.JSON(http.StatusInternalServerError, gin.H{
|
||||||
|
|||||||
43
controllers/ex_controller.go
Normal file
43
controllers/ex_controller.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package controllers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"GinTutorial/global"
|
||||||
|
"GinTutorial/models"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateExchangeRate(ctx *gin.Context) {
|
||||||
|
var exchangeRate models.ExchangeRate
|
||||||
|
|
||||||
|
if err := ctx.ShouldBindJSON(&exchangeRate); err != nil {
|
||||||
|
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
exchangeRate.Date = time.Now()
|
||||||
|
|
||||||
|
if err := global.Db.AutoMigrate(&exchangeRate); err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := global.Db.Create(&exchangeRate).Error; err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusCreated, gin.H{"data": exchangeRate})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetExchangeRates(ctx *gin.Context) {
|
||||||
|
var exchangeRates []models.ExchangeRate
|
||||||
|
|
||||||
|
if err := global.Db.Find(&exchangeRates).Error; err != nil {
|
||||||
|
ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.JSON(http.StatusOK, gin.H{"data": exchangeRates})
|
||||||
|
}
|
||||||
28
middlewares/auth_middleware.go
Normal file
28
middlewares/auth_middleware.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package middlewares
|
||||||
|
|
||||||
|
import (
|
||||||
|
"GinTutorial/utils"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuthMiddleWare() gin.HandlerFunc {
|
||||||
|
return func(ctx *gin.Context) {
|
||||||
|
token := ctx.GetHeader("Authorization")
|
||||||
|
if token == "" {
|
||||||
|
ctx.JSON(http.StatusUnauthorized, gin.H{"message": "Token is empty"})
|
||||||
|
ctx.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
username, err := utils.ParseToken(token)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid Token"})
|
||||||
|
ctx.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Set("username", username)
|
||||||
|
ctx.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
11
models/ex_rate.go
Normal file
11
models/ex_rate.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type ExchangeRate struct {
|
||||||
|
ID uint `gorm:"primary_key" json:"_id"`
|
||||||
|
FromCurrency string `json:"from_currency" binding:"required"`
|
||||||
|
ToCurrency string `json:"to_currency" binding:"required"`
|
||||||
|
Rate float64 `json:"rate" binding:"required"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"GinTutorial/controllers"
|
"GinTutorial/controllers"
|
||||||
|
"GinTutorial/middlewares"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
@@ -17,6 +18,13 @@ func SetupRouter() *gin.Engine {
|
|||||||
auth.POST("/login", controllers.Login)
|
auth.POST("/login", controllers.Login)
|
||||||
auth.POST("/register", controllers.Register)
|
auth.POST("/register", controllers.Register)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ex := v1.Group("/ex")
|
||||||
|
{
|
||||||
|
ex.GET("/exchangeRates", controllers.GetExchangeRates)
|
||||||
|
ex.Use(middlewares.AuthMiddleWare())
|
||||||
|
ex.POST("/exchangeRates", controllers.CreateExchangeRate)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package utils
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"GinTutorial/config"
|
"GinTutorial/config"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
@@ -19,7 +21,7 @@ func GenerateJWT(username string) (string, error) {
|
|||||||
"exp": time.Now().Add(time.Hour * 72).Unix(),
|
"exp": time.Now().Add(time.Hour * 72).Unix(),
|
||||||
})
|
})
|
||||||
|
|
||||||
signedToken, err := token.SignedString([]byte("secret"))
|
signedToken, err := token.SignedString([]byte(config.AppConfig.Jwtconfig.Secret))
|
||||||
return "Bearer " + signedToken, err
|
return "Bearer " + signedToken, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,3 +29,29 @@ func CheckPassword(password, hash string) bool {
|
|||||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseToken(tokenString string) (string, error) {
|
||||||
|
if len(tokenString) > 7 && tokenString[0:7] == "Bearer " {
|
||||||
|
tokenString = tokenString[7:]
|
||||||
|
}
|
||||||
|
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||||
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
|
}
|
||||||
|
return []byte(config.AppConfig.Jwtconfig.Secret), nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||||
|
username, ok := claims["username"].(string)
|
||||||
|
if !ok {
|
||||||
|
return "", errors.New("username invalid")
|
||||||
|
}
|
||||||
|
return username, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", errors.New("token invalid")
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user