mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-01 14:46:36 +08:00
[优化] 更换 JWT 认证机制
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
|
||||
jwt "github.com/appleboy/gin-jwt/v2"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const OpenFlareTokenHeader = "OpenFlare-Token"
|
||||
|
||||
func authHelper(c *gin.Context, minRole int) {
|
||||
token := c.GetHeader(OpenFlareTokenHeader)
|
||||
if token == "" {
|
||||
tokenStr := c.GetHeader(OpenFlareTokenHeader)
|
||||
if tokenStr == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,未登录或 token 无效",
|
||||
@@ -20,16 +22,49 @@ func authHelper(c *gin.Context, minRole int) {
|
||||
return
|
||||
}
|
||||
|
||||
user := model.ValidateUserToken(token)
|
||||
if user == nil || user.Username == "" {
|
||||
token, err := JWTMiddleware.ParseTokenString(tokenStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,token 无效",
|
||||
"message": "无权进行此操作,token 无效: " + err.Error(),
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if user.Status == common.UserStatusDisabled {
|
||||
|
||||
claims := jwt.ExtractClaimsFromToken(token)
|
||||
id, ok := claims["id"].(float64)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,token 格式错误",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
dbUser := &model.User{}
|
||||
dbErr := model.DB.Select([]string{"id", "username", "display_name", "role", "status", "token"}).
|
||||
First(dbUser, "id = ?", int(id)).Error
|
||||
if dbErr != nil || dbUser.Username == "" {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,用户不存在",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if dbUser.Token != tokenStr {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,token 已失效或已登出",
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
|
||||
if dbUser.Status == common.UserStatusDisabled {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "用户已被封禁",
|
||||
@@ -37,7 +72,8 @@ func authHelper(c *gin.Context, minRole int) {
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
if user.Role < minRole {
|
||||
|
||||
if int(dbUser.Role) < minRole {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,权限不足",
|
||||
@@ -45,9 +81,10 @@ func authHelper(c *gin.Context, minRole int) {
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Set("username", user.Username)
|
||||
c.Set("role", user.Role)
|
||||
c.Set("id", user.Id)
|
||||
|
||||
c.Set("username", dbUser.Username)
|
||||
c.Set("role", dbUser.Role)
|
||||
c.Set("id", dbUser.Id)
|
||||
c.Set("authByToken", true)
|
||||
c.Next()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"log"
|
||||
"openflare/common"
|
||||
"openflare/model"
|
||||
"time"
|
||||
|
||||
jwt "github.com/appleboy/gin-jwt/v2"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var JWTMiddleware *jwt.GinJWTMiddleware
|
||||
|
||||
// jwtSigningKey returns JWT_SECRET when set, falling back to SESSION_SECRET
|
||||
// for backward compatibility with deployments that only configure SESSION_SECRET.
|
||||
func jwtSigningKey() []byte {
|
||||
if common.JWTSecret != "" {
|
||||
return []byte(common.JWTSecret)
|
||||
}
|
||||
return []byte(common.SessionSecret)
|
||||
}
|
||||
|
||||
func InitJWTMiddleware() {
|
||||
var err error
|
||||
JWTMiddleware, err = jwt.New(&jwt.GinJWTMiddleware{
|
||||
Realm: "openflare",
|
||||
Key: jwtSigningKey(),
|
||||
Timeout: 24 * time.Hour,
|
||||
MaxRefresh: 24 * time.Hour,
|
||||
IdentityKey: "identity",
|
||||
PayloadFunc: func(data interface{}) jwt.MapClaims {
|
||||
if v, ok := data.(*model.User); ok {
|
||||
return jwt.MapClaims{
|
||||
"id": v.Id,
|
||||
"username": v.Username,
|
||||
"role": v.Role,
|
||||
}
|
||||
}
|
||||
return jwt.MapClaims{}
|
||||
},
|
||||
IdentityHandler: func(c *gin.Context) interface{} {
|
||||
claims := jwt.ExtractClaims(c)
|
||||
id, ok := claims["id"].(float64)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
username, _ := claims["username"].(string)
|
||||
role, _ := claims["role"].(float64)
|
||||
return &model.User{
|
||||
Id: int(id),
|
||||
Username: username,
|
||||
Role: int(role),
|
||||
}
|
||||
},
|
||||
Authorizator: func(data interface{}, c *gin.Context) bool {
|
||||
return data != nil
|
||||
},
|
||||
Unauthorized: func(c *gin.Context, code int, message string) {
|
||||
c.JSON(code, gin.H{
|
||||
"success": false,
|
||||
"message": "无权进行此操作,未登录或 token 无效: " + message,
|
||||
})
|
||||
},
|
||||
TokenLookup: "header: OpenFlare-Token",
|
||||
TokenHeadName: "", // Empty for raw token value directly
|
||||
SendCookie: false,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("JWT Init Error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user