Compare commits

...

6 Commits

Author SHA1 Message Date
zhaoxiaorong
b5374b85ff fix 2025-04-09 10:56:49 +08:00
zhaoxiaorong
5172824358 fix 2025-04-09 10:34:01 +08:00
zhaoxiaorong
51ff7d1ffd fix 2025-04-09 10:19:15 +08:00
zhaoxiaorong
c7f24e3b6d fix 2025-04-09 09:39:51 +08:00
f7948263c5 Merge branch 'main' of https://git.apinb.com/bsm-sdk/core 2025-04-08 15:20:34 +08:00
fc42bc92ff fix parse meta ctx 2025-04-08 15:20:22 +08:00
4 changed files with 89 additions and 40 deletions

View File

@@ -17,14 +17,14 @@ var (
type service struct{} type service struct{}
func (s *service) Register(cli *clientv3.Client, serviceName string, port int) error { func (s *service) Register(cli *clientv3.Client, serviceName string, port string) error {
lease := clientv3.NewLease(cli) lease := clientv3.NewLease(cli)
grantResp, err := lease.Grant(context.TODO(), 5) grantResp, err := lease.Grant(context.TODO(), 5)
if err != nil { if err != nil {
return err return err
} }
serviceAddr := utils.GetLocationIP() + ":" + utils.Int2String(port) serviceAddr := utils.GetLocationIP() + ":" + port
key := RootPrefix + serviceName + "/" + utils.Int642String(time.Now().UnixNano()) key := RootPrefix + serviceName + "/" + utils.Int642String(time.Now().UnixNano())
_, err = cli.KV.Put(context.TODO(), key, serviceAddr, clientv3.WithLease(grantResp.ID)) _, err = cli.KV.Put(context.TODO(), key, serviceAddr, clientv3.WithLease(grantResp.ID))

73
middleware/jwt.go Normal file
View File

@@ -0,0 +1,73 @@
package middleware
import (
"encoding/json"
"fmt"
"log"
"net/http"
"git.apinb.com/bsm-sdk/core/cache/redis"
"git.apinb.com/bsm-sdk/core/crypto/encipher"
"git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/types"
"github.com/gin-gonic/gin"
)
func JwtAuth(redis *redis.RedisClient) gin.HandlerFunc {
return func(c *gin.Context) {
// 从请求头中获取 Authorization
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
log.Println("获取token异常:", "Authorization header is required")
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header is required"})
c.Abort()
return
}
// 提取Token
claims, err := encipher.ParseTokenAes(authHeader)
if err != nil || claims == nil {
log.Println("提取token异常:", "Token is required")
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token is required"})
c.Abort()
return
}
// 从redis 获取token,判断当前redis 是否为空
tokenKey := fmt.Sprintf("%d-%s-%s", claims.ID, claims.Role, "token")
redisToken := redis.Client.Get(redis.Ctx, tokenKey)
if redisToken.Val() == "" {
log.Println("redis异常", "Token status unauthorized")
c.JSON(http.StatusUnauthorized, gin.H{"error": "Token status unauthorized"})
c.Abort()
return
}
// 将解析后的 Token 存储到上下文中
c.Set("Auth", claims)
// 如果 Token 有效,继续处理请求
c.Next()
}
}
// 获取上下文用户登录信息
func ParseAuth(c *gin.Context) (*types.JwtClaims, error) {
claims, ok := c.Get("Auth")
if !ok {
log.Printf("获取登录信息异常: %v", errcode.ErrJWTAuthNotFound)
return nil, errcode.ErrJWTAuthNotFound
}
json_claims, err := json.Marshal(claims)
if err != nil {
log.Printf("解析json异常: %v", err)
return nil, errcode.ErrJsonMarshal
}
var auth *types.JwtClaims
if err := json.Unmarshal(json_claims, &auth); err != nil {
log.Printf("解析json异常: %v", err)
return nil, errcode.ErrJsonUnmarshal
}
return auth, nil
}

View File

@@ -2,81 +2,57 @@ package service
import ( import (
"context" "context"
"encoding/json"
"strconv"
"git.apinb.com/bsm-sdk/core/crypto/encipher"
"git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/errcode"
"git.apinb.com/bsm-sdk/core/types"
"git.apinb.com/bsm-sdk/core/utils" "git.apinb.com/bsm-sdk/core/utils"
"google.golang.org/grpc/metadata" "google.golang.org/grpc/metadata"
) )
type Meta struct {
ID uint `json:"id"`
IDENTITY string `json:"identity"`
EXTEND map[string]string `json:"extend"`
CLIENT string `json:"client"`
}
// 解析Context中MetaData的数据 // 解析Context中MetaData的数据
type ParseOptions struct { type ParseOptions struct {
RoleValue string // 判断角色的值 RoleValue string // 判断角色的值
MustPrivateAllow bool // 是否只允许私有IP访问 MustPrivateAllow bool // 是否只允许私有IP访问
} }
func ParseMetaCtx(ctx context.Context, opts *ParseOptions) (*Meta, error) { func ParseMetaCtx(ctx context.Context, opts *ParseOptions) (*types.JwtClaims, error) {
// 解析metada中的信息并验证 // 解析metada中的信息并验证
md, ok := metadata.FromIncomingContext(ctx) md, ok := metadata.FromIncomingContext(ctx)
if !ok { if !ok {
return nil, errcode.ErrJWTAuthNotFound return nil, errcode.ErrJWTAuthNotFound
} }
// 安全获取 metadata 中的值 var Authorizations []string = md.Get("authorization")
identityValues := md.Get("authorization_identity") if len(Authorizations) == 0 || Authorizations[0] == "" {
clientValues := md.Get("client")
if len(identityValues) == 0 {
return nil, errcode.ErrJWTAuthNotFound
}
if len(clientValues) == 0 {
return nil, errcode.ErrJWTAuthNotFound return nil, errcode.ErrJWTAuthNotFound
} }
meta := &Meta{ claims, err := encipher.ParseTokenAes(Authorizations[0])
IDENTITY: md["authorization_identity"][0], if err != nil {
CLIENT: md["client"][0], return nil, err
}
if id, err := strconv.Atoi(md["authorization_id"][0]); err != nil {
return nil, errcode.ErrJWTAuthKeyId
} else {
meta.ID = uint(id)
}
data := make(map[string]string)
if err := json.Unmarshal([]byte(md["authorization_extend"][0]), &data); err == nil {
meta.EXTEND = data
} }
if opts != nil { if opts != nil {
if !meta.CheckRole("role", opts.RoleValue) { if !checkRole(claims, "role", opts.RoleValue) {
return nil, errcode.ErrPermissionDenied return nil, errcode.ErrPermissionDenied
} }
if opts.MustPrivateAllow { if opts.MustPrivateAllow {
if utils.IsPublicIP(meta.CLIENT) { if utils.IsPublicIP(claims.Client) {
return nil, errcode.ErrPermissionDenied return nil, errcode.ErrPermissionDenied
} }
} }
} }
return meta, nil return claims, nil
} }
func (m *Meta) CheckRole(roleKey, roleValue string) bool { func checkRole(claims *types.JwtClaims, roleKey, roleValue string) bool {
if roleValue == "" { if roleValue == "" {
return true return true
} }
if role, exists := m.EXTEND[roleKey]; !exists || role != roleValue { if role, exists := claims.Extend[roleKey]; !exists || role != roleValue {
return false return false
} else { } else {
return true return true

View File

@@ -31,7 +31,7 @@ type (
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"` DeletedAt gorm.DeletedAt `gorm:"index;" json:"deleted_at"`
Status int64 `gorm:"default:0;index;" json:"status"` // 状态默认为0-1禁止1为正常 Status int8 `gorm:"default:0;index;" json:"status"` // 状态默认为0-1禁止1为正常
} }
// standard ID,Identity,Created,Updated,Deleted,Status definition. // standard ID,Identity,Created,Updated,Deleted,Status definition.