You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 lines
3.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package biz
import (
"context"
"moredoc/model"
"strings"
"time"
"github.com/gin-gonic/gin"
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
"go.uber.org/zap"
"google.golang.org/grpc"
)
/*
当前中间件的作用主要是将用户的token信息解析存放到ctx中方便后续的业务逻辑使用。
这里无论用户登录与否都会执行该中间件如果用户登录则会将用户信息存放到ctx中否则ctx中不会有用户信息。
*/
type AuthService struct {
dbModel *model.DBModel
logger *zap.Logger
}
func NewAuthService(dbModel *model.DBModel, logger *zap.Logger) (service *UserAPIService) {
return &UserAPIService{dbModel: dbModel, logger: logger.Named("AuthService")}
}
type ContextKey string
func (ck ContextKey) String() string {
return string(ck)
}
const (
CtxKeyUserClaims ContextKey = "user"
)
// const (
// messageInvalidToken = "您的登录令牌已过期,请重新登录"
// )
type ServiceAuthFuncOverride interface {
AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error)
}
func (s *AuthService) AuthUnaryServerInterceptor() grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
newCtx, err := s.AuthGRPC(ctx, info)
if err != nil {
return nil, err
}
return handler(newCtx, req)
}
}
// AuthGRPC 验证 gRPC 请求
// 1. 从权限表中查询API如果存在该API则表示该API需要权限才能访问如果不存在则跳过
// 2. 如果用户携带有token则根据token判断是否有效如果有效则获取用户信息放到ctx否则跳过
func (s *AuthService) AuthGRPC(ctx context.Context, info *grpc.UnaryServerInfo) (context.Context, error) {
token, err := grpc_auth.AuthFromMD(ctx, "bearer")
if err != nil {
return ctx, nil
}
claims, err := s.dbModel.CheckUserJWTToken(token)
// token存在但是不正确或者已过期这时需要返回错误前端清除存储的错误登录信息
if err != nil || claims == nil || claims.ExpiresAt < time.Now().Unix() || s.dbModel.IsInvalidToken(claims.UUID) {
// return ctx, status.Error(codes.Unauthenticated, messageInvalidToken)
return ctx, nil
}
newCtx := context.WithValue(ctx, CtxKeyUserClaims, claims)
return newCtx, nil
}
// AuthGin 验证 HTTP 请求
func (s *AuthService) AuthGin() gin.HandlerFunc {
return func(ctx *gin.Context) {
auth := ctx.Request.Header.Get("authorization")
bearer := strings.Split(auth, " ")
if auth == "" || len(bearer) != 2 {
ctx.Next()
return
}
token := bearer[1]
claims, err := s.dbModel.CheckUserJWTToken(token)
if err != nil || claims == nil || claims.ExpiresAt < time.Now().Unix() || s.dbModel.IsInvalidToken(claims.UUID) {
// ctx.JSON(http.StatusUnauthorized, status.Error(codes.Unauthenticated, messageInvalidToken))
// ctx.Abort()
ctx.Next()
return
}
ctx.Set(CtxKeyUserClaims.String(), claims)
ctx.Next()
}
}