package pub import ( "context" "crypto/subtle" "errors" "time" "perms-system-server/internal/consts" authHelper "perms-system-server/internal/logic/auth" "perms-system-server/internal/model/user" "perms-system-server/internal/response" "perms-system-server/internal/svc" "perms-system-server/internal/types" "github.com/zeromicro/go-zero/core/limit" "github.com/zeromicro/go-zero/core/logx" "golang.org/x/crypto/bcrypt" ) type AdminLoginLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewAdminLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminLoginLogic { return &AdminLoginLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // AdminLogin 管理后台登录。仅限超级管理员通过 managementKey + 用户名密码登录管理后台,返回 JWT 令牌对。 func (l *AdminLoginLogic) AdminLogin(req *types.AdminLoginReq) (resp *types.LoginResp, err error) { if subtle.ConstantTimeCompare([]byte(req.ManagementKey), []byte(l.svcCtx.Config.Auth.ManagementKey)) != 1 { return nil, response.ErrUnauthorized("managementKey无效") } if l.svcCtx.UsernameLoginLimit != nil { code, _ := l.svcCtx.UsernameLoginLimit.Take(req.Username) if code == limit.OverQuota { return nil, response.NewCodeError(429, "该账号登录尝试过于频繁,请5分钟后再试") } } u, err := l.svcCtx.SysUserModel.FindOneByUsername(l.ctx, req.Username) if err != nil { if errors.Is(err, user.ErrNotFound) { return nil, response.ErrUnauthorized("用户名或密码错误") } return nil, err } if u.Status != consts.StatusEnabled { return nil, response.ErrForbidden("账号已被冻结") } if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(req.Password)); err != nil { return nil, response.ErrUnauthorized("用户名或密码错误") } if u.IsSuperAdmin != consts.IsSuperAdminYes { return nil, response.ErrForbidden("仅超级管理员可通过管理后台登录") } ud := l.svcCtx.UserDetailsLoader.Load(l.ctx, u.Id, "") accessToken, err := authHelper.GenerateAccessToken( l.svcCtx.Config.Auth.AccessSecret, l.svcCtx.Config.Auth.AccessExpire, ud.UserId, ud.Username, ud.ProductCode, ud.MemberType, ud.TokenVersion, ) if err != nil { return nil, err } refreshToken, err := authHelper.GenerateRefreshToken( l.svcCtx.Config.Auth.RefreshSecret, l.svcCtx.Config.Auth.RefreshExpire, ud.UserId, ud.ProductCode, ud.TokenVersion, ) if err != nil { return nil, err } return &types.LoginResp{ AccessToken: accessToken, RefreshToken: refreshToken, Expires: time.Now().Unix() + l.svcCtx.Config.Auth.AccessExpire, UserInfo: types.UserInfo{ UserId: ud.UserId, Username: ud.Username, Nickname: ud.Nickname, Avatar: ud.Avatar, Email: ud.Email, Phone: ud.Phone, IsSuperAdmin: ud.IsSuperAdminRaw, MustChangePassword: ud.MustChangePwdRaw, MemberType: ud.MemberType, Perms: ud.Perms, }, }, nil }