mingyang-admin-iot-app/api/internal/logic/user/logout_logic.go

126 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package user
import (
"bytes"
"context"
"github.com/saas-mingyang/mingyang-admin-common/i18n"
"mingyang-admin-app-api/internal/svc"
"mingyang-admin-app-api/internal/types"
"mingyang-admin-app-rpc/types/app"
"net/http"
"runtime"
"strconv"
"strings"
"time"
"github.com/zeromicro/go-zero/core/logx"
)
type LogoutLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewLogoutLogic(ctx context.Context, svcCtx *svc.ServiceContext) *LogoutLogic {
return &LogoutLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
// Logout 在API层添加调用栈信息
func (l *LogoutLogic) Logout() (resp *types.BaseMsgResp, err error) {
// 打印调用栈
buf := make([]byte, 1024)
n := runtime.Stack(buf, false)
l.Logger.Infof("Logout call stack:\n%s", buf[:n])
token := l.getTokenFromContext()
l.Infof("Starting Logout RPC call at: %v", time.Now())
// 记录goroutine ID
goID := getGoroutineID()
l.Logger.Infof("Goroutine ID: %d", goID)
_, err = l.svcCtx.AppRpc.LogoutUser(l.ctx, &app.UserToken{
AccessToken: token,
UserId: l.getUserIDFromContext(),
})
l.Logger.Infof("Finished Logout RPC call at: %v", time.Now())
if err != nil {
return nil, err
}
return &types.BaseMsgResp{Msg: l.svcCtx.Trans.Trans(l.ctx, i18n.Success)}, nil
}
// 获取goroutine ID
func getGoroutineID() uint64 {
b := make([]byte, 64)
b = b[:runtime.Stack(b, false)]
b = bytes.TrimPrefix(b, []byte("goroutine "))
b = b[:bytes.IndexByte(b, ' ')]
n, _ := strconv.ParseUint(string(b), 10, 64)
return n
}
// 从上下文中获取 Token
func (l *LogoutLogic) getTokenFromContext() string {
// 尝试不同的 key 从上下文中获取 Token
keys := []string{"token", "access_token", "jwt_token", "auth_token"}
for _, key := range keys {
if token, ok := l.ctx.Value(key).(string); ok && token != "" {
return l.cleanToken(token)
}
}
return ""
}
// 清理 Token 字符串,移除 "Bearer " 前缀
func (l *LogoutLogic) cleanToken(token string) string {
if token == "" {
return ""
}
token = strings.TrimSpace(token)
// 移除 "Bearer " 前缀
if strings.HasPrefix(strings.ToLower(token), "bearer ") {
token = token[7:]
}
return token
}
// 从 Authorization Header 中提取 Token
func (l *LogoutLogic) extractTokenFromAuthHeader(ctx context.Context) string {
// 尝试从请求上下文获取 Request 对象
if req, ok := ctx.Value("http_request").(*http.Request); ok {
authHeader := req.Header.Get("Authorization")
if authHeader != "" {
return l.cleanToken(authHeader)
}
}
return ""
}
// 从上下文中获取用户ID
func (l *LogoutLogic) getUserIDFromContext() uint64 {
// 在AuthMiddleware中我们将用户ID放入了context
if userID, ok := l.ctx.Value("userId").(uint64); ok {
return userID
}
return 0
}
// 获取 Token 过期时间
func (l *LogoutLogic) getTokenExpireTime(token string) (time.Time, error) {
// 使用 JWTManager 验证并获取 Claims
claims, err := l.svcCtx.AppRpc.AuthToken(l.ctx, &app.AuthReq{Token: token})
if err != nil {
return time.Time{}, err
}
return claims.Claims.ExpiresAt.Timestamp.AsTime(), nil
}