mirror of
https://github.com/yv1ing/gin-admin.git
synced 2025-10-24 10:12:05 +08:00
添加jwt鉴权中间件
This commit is contained in:
81
internal/middleware/auth.go
Normal file
81
internal/middleware/auth.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-admin/internal/core/config"
|
||||
"gin-admin/pkg/auth"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
systemmodel "gin-admin/internal/model/system"
|
||||
)
|
||||
|
||||
// @Author: yv1ing
|
||||
// @Author: me@yvling.cn
|
||||
// @Date: 2025/8/28 17:31
|
||||
// @Desc: 鉴权中间件
|
||||
|
||||
func extractBearerToken(c *gin.Context) string {
|
||||
authorization := c.GetHeader("Authorization")
|
||||
if authorization == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
parts := strings.SplitN(authorization, " ", 2)
|
||||
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") || parts[1] == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
return parts[1]
|
||||
}
|
||||
|
||||
func JwtMiddleware(whitelist []string) gin.HandlerFunc {
|
||||
var whitelistRegex []*regexp.Regexp
|
||||
for _, pattern := range whitelist {
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err == nil {
|
||||
whitelistRegex = append(whitelistRegex, re)
|
||||
}
|
||||
}
|
||||
|
||||
return func(c *gin.Context) {
|
||||
path := c.Request.URL.Path
|
||||
for _, re := range whitelistRegex {
|
||||
if re.MatchString(path) {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
tokenStr := extractBearerToken(c)
|
||||
if tokenStr == "" {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, systemmodel.Response{
|
||||
Code: http.StatusUnauthorized,
|
||||
Info: "请求头Authorization非法或缺失",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := auth.ParseAccessToken(tokenStr, config.Config.SecretKey)
|
||||
if err != nil {
|
||||
if errors.Is(err, jwt.ErrTokenExpired) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, systemmodel.Response{
|
||||
Code: http.StatusUnauthorized,
|
||||
Info: "Token已过期",
|
||||
})
|
||||
} else {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, systemmodel.Response{
|
||||
Code: http.StatusUnauthorized,
|
||||
Info: "Token不合法",
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.Set("UID", claims.ID)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"gin-admin/internal/middleware"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
systemapi "gin-admin/internal/api/system"
|
||||
@@ -11,7 +12,13 @@ import (
|
||||
// @Date: 2025/8/28 16:17
|
||||
// @Desc: 路由注册入口
|
||||
|
||||
var whitelist = []string{
|
||||
`^/api/sys/login$`,
|
||||
}
|
||||
|
||||
func SetupRoutes(eng *gin.Engine) {
|
||||
eng.Use(middleware.JwtMiddleware(whitelist))
|
||||
|
||||
api := eng.Group("/api")
|
||||
|
||||
/* 系统内置接口 */
|
||||
|
||||
@@ -2,9 +2,9 @@ package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-admin/internal/auth"
|
||||
"gin-admin/internal/core/config"
|
||||
"gin-admin/internal/repository"
|
||||
"gin-admin/pkg/auth"
|
||||
"gin-admin/pkg/encrypt"
|
||||
"gorm.io/gorm"
|
||||
|
||||
@@ -31,7 +31,7 @@ func SysUserLogin(username, password string) (string, error) {
|
||||
return "", errors.New("用户已被禁用")
|
||||
}
|
||||
|
||||
jwtToken, err := auth.CreateAccessToken(user.ID, user.Username, 3600)
|
||||
jwtToken, err := auth.CreateAccessToken(user.ID, user.Username, config.Config.SecretKey)
|
||||
if err != nil {
|
||||
return "", errors.New("系统内部错误")
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package auth
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-admin/internal/core/config"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"time"
|
||||
)
|
||||
@@ -19,8 +18,8 @@ type AccessClaims struct {
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func CreateAccessToken(ID uint, username string, ttl time.Duration) (string, error) {
|
||||
jwtSecret := []byte(config.Config.SecretKey)
|
||||
func CreateAccessToken(ID uint, username string, secretKey string) (string, error) {
|
||||
jwtSecret := []byte(secretKey)
|
||||
|
||||
claims := AccessClaims{
|
||||
ID: ID,
|
||||
@@ -28,7 +27,7 @@ func CreateAccessToken(ID uint, username string, ttl time.Duration) (string, err
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
Subject: "gin-admin",
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(ttl)),
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(12 * time.Hour)),
|
||||
ID: fmt.Sprintf("%d-%d", ID, time.Now().UnixNano()),
|
||||
},
|
||||
}
|
||||
@@ -37,8 +36,8 @@ func CreateAccessToken(ID uint, username string, ttl time.Duration) (string, err
|
||||
return token.SignedString(jwtSecret)
|
||||
}
|
||||
|
||||
func ParseAccessToken(tokenStr string) (*AccessClaims, error) {
|
||||
jwtSecret := []byte(config.Config.SecretKey)
|
||||
func ParseAccessToken(tokenStr, secretKey string) (*AccessClaims, error) {
|
||||
jwtSecret := []byte(secretKey)
|
||||
token, err := jwt.ParseWithClaims(tokenStr, &AccessClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return jwtSecret, nil
|
||||
})
|
||||
Reference in New Issue
Block a user