adminLoginLogic.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package pub
  2. import (
  3. "context"
  4. "crypto/subtle"
  5. "errors"
  6. "time"
  7. "perms-system-server/internal/consts"
  8. authHelper "perms-system-server/internal/logic/auth"
  9. "perms-system-server/internal/model/user"
  10. "perms-system-server/internal/response"
  11. "perms-system-server/internal/svc"
  12. "perms-system-server/internal/types"
  13. "github.com/zeromicro/go-zero/core/limit"
  14. "github.com/zeromicro/go-zero/core/logx"
  15. "golang.org/x/crypto/bcrypt"
  16. )
  17. type AdminLoginLogic struct {
  18. logx.Logger
  19. ctx context.Context
  20. svcCtx *svc.ServiceContext
  21. }
  22. func NewAdminLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminLoginLogic {
  23. return &AdminLoginLogic{
  24. Logger: logx.WithContext(ctx),
  25. ctx: ctx,
  26. svcCtx: svcCtx,
  27. }
  28. }
  29. // AdminLogin 管理后台登录。仅限超级管理员通过 managementKey + 用户名密码登录管理后台,返回 JWT 令牌对。
  30. func (l *AdminLoginLogic) AdminLogin(req *types.AdminLoginReq) (resp *types.LoginResp, err error) {
  31. if subtle.ConstantTimeCompare([]byte(req.ManagementKey), []byte(l.svcCtx.Config.Auth.ManagementKey)) != 1 {
  32. return nil, response.ErrUnauthorized("managementKey无效")
  33. }
  34. if l.svcCtx.UsernameLoginLimit != nil {
  35. code, _ := l.svcCtx.UsernameLoginLimit.Take(req.Username)
  36. if code == limit.OverQuota {
  37. return nil, response.NewCodeError(429, "该账号登录尝试过于频繁,请5分钟后再试")
  38. }
  39. }
  40. u, err := l.svcCtx.SysUserModel.FindOneByUsername(l.ctx, req.Username)
  41. if err != nil {
  42. if errors.Is(err, user.ErrNotFound) {
  43. bcrypt.CompareHashAndPassword(dummyBcryptHash, []byte(req.Password))
  44. return nil, response.ErrUnauthorized("用户名或密码错误")
  45. }
  46. return nil, err
  47. }
  48. if err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(req.Password)); err != nil {
  49. return nil, response.ErrUnauthorized("用户名或密码错误")
  50. }
  51. if u.Status != consts.StatusEnabled {
  52. return nil, response.ErrUnauthorized("用户名或密码错误")
  53. }
  54. if u.IsSuperAdmin != consts.IsSuperAdminYes {
  55. return nil, response.ErrUnauthorized("用户名或密码错误")
  56. }
  57. ud := l.svcCtx.UserDetailsLoader.Load(l.ctx, u.Id, "")
  58. accessToken, err := authHelper.GenerateAccessToken(
  59. l.svcCtx.Config.Auth.AccessSecret,
  60. l.svcCtx.Config.Auth.AccessExpire,
  61. ud.UserId, ud.Username, ud.ProductCode, ud.MemberType, ud.TokenVersion,
  62. )
  63. if err != nil {
  64. return nil, err
  65. }
  66. refreshToken, err := authHelper.GenerateRefreshToken(
  67. l.svcCtx.Config.Auth.RefreshSecret,
  68. l.svcCtx.Config.Auth.RefreshExpire,
  69. ud.UserId, ud.ProductCode, ud.TokenVersion,
  70. )
  71. if err != nil {
  72. return nil, err
  73. }
  74. return &types.LoginResp{
  75. AccessToken: accessToken,
  76. RefreshToken: refreshToken,
  77. Expires: time.Now().Unix() + l.svcCtx.Config.Auth.AccessExpire,
  78. UserInfo: types.UserInfo{
  79. UserId: ud.UserId,
  80. Username: ud.Username,
  81. Nickname: ud.Nickname,
  82. Avatar: ud.Avatar,
  83. Email: ud.Email,
  84. Phone: ud.Phone,
  85. IsSuperAdmin: ud.IsSuperAdminRaw,
  86. MustChangePassword: ud.MustChangePwdRaw,
  87. MemberType: ud.MemberType,
  88. Perms: ud.Perms,
  89. },
  90. }, nil
  91. }