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
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"gin-admin/internal/middleware"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
systemapi "gin-admin/internal/api/system"
|
systemapi "gin-admin/internal/api/system"
|
||||||
@@ -11,7 +12,13 @@ import (
|
|||||||
// @Date: 2025/8/28 16:17
|
// @Date: 2025/8/28 16:17
|
||||||
// @Desc: 路由注册入口
|
// @Desc: 路由注册入口
|
||||||
|
|
||||||
|
var whitelist = []string{
|
||||||
|
`^/api/sys/login$`,
|
||||||
|
}
|
||||||
|
|
||||||
func SetupRoutes(eng *gin.Engine) {
|
func SetupRoutes(eng *gin.Engine) {
|
||||||
|
eng.Use(middleware.JwtMiddleware(whitelist))
|
||||||
|
|
||||||
api := eng.Group("/api")
|
api := eng.Group("/api")
|
||||||
|
|
||||||
/* 系统内置接口 */
|
/* 系统内置接口 */
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ package system
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"gin-admin/internal/auth"
|
|
||||||
"gin-admin/internal/core/config"
|
"gin-admin/internal/core/config"
|
||||||
"gin-admin/internal/repository"
|
"gin-admin/internal/repository"
|
||||||
|
"gin-admin/pkg/auth"
|
||||||
"gin-admin/pkg/encrypt"
|
"gin-admin/pkg/encrypt"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ func SysUserLogin(username, password string) (string, error) {
|
|||||||
return "", errors.New("用户已被禁用")
|
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 {
|
if err != nil {
|
||||||
return "", errors.New("系统内部错误")
|
return "", errors.New("系统内部错误")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package auth
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"gin-admin/internal/core/config"
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -19,8 +18,8 @@ type AccessClaims struct {
|
|||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateAccessToken(ID uint, username string, ttl time.Duration) (string, error) {
|
func CreateAccessToken(ID uint, username string, secretKey string) (string, error) {
|
||||||
jwtSecret := []byte(config.Config.SecretKey)
|
jwtSecret := []byte(secretKey)
|
||||||
|
|
||||||
claims := AccessClaims{
|
claims := AccessClaims{
|
||||||
ID: ID,
|
ID: ID,
|
||||||
@@ -28,7 +27,7 @@ func CreateAccessToken(ID uint, username string, ttl time.Duration) (string, err
|
|||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
Subject: "gin-admin",
|
Subject: "gin-admin",
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
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()),
|
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)
|
return token.SignedString(jwtSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseAccessToken(tokenStr string) (*AccessClaims, error) {
|
func ParseAccessToken(tokenStr, secretKey string) (*AccessClaims, error) {
|
||||||
jwtSecret := []byte(config.Config.SecretKey)
|
jwtSecret := []byte(secretKey)
|
||||||
token, err := jwt.ParseWithClaims(tokenStr, &AccessClaims{}, func(token *jwt.Token) (interface{}, error) {
|
token, err := jwt.ParseWithClaims(tokenStr, &AccessClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||||
return jwtSecret, nil
|
return jwtSecret, nil
|
||||||
})
|
})
|
||||||
Reference in New Issue
Block a user