login.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package account
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "mtp20access/global"
  6. accountModel "mtp20access/model/account"
  7. "mtp20access/model/account/request"
  8. jwtRequest "mtp20access/model/common/request"
  9. "sync"
  10. "mtp20access/utils"
  11. "strconv"
  12. "go.uber.org/zap"
  13. )
  14. var (
  15. mtx sync.RWMutex
  16. curSessionID int = 90000 // 本服务SessionID从90000开始,以避免与旧登录服务重叠
  17. )
  18. // Login 用户登录
  19. func Login(req request.LoginReq, addr string) (loginaccount *accountModel.Loginaccount, token string, expiresAt int64, err error) {
  20. // 分别尝试用LoginID、LoginCode和手机号码进行登录
  21. loginaccount, err = getLoginAccount(req.UserName, req.Password)
  22. if err != nil {
  23. return
  24. }
  25. // 判断用户状态
  26. if loginaccount.LOGINSTATUS == 2 {
  27. err = errors.New("账户已冻结")
  28. return
  29. }
  30. if loginaccount.LOGINSTATUS == 3 {
  31. err = errors.New("账户已注销")
  32. return
  33. }
  34. // 生成Token,并写入Redis
  35. if token, expiresAt, err = buildRedisLoginInfo(*loginaccount, addr, req.ClientType); err != nil {
  36. return
  37. }
  38. return
  39. }
  40. // getLoginAccount 分别尝试用LoginID、LoginCode和手机号码进行登录
  41. func getLoginAccount(userName string, password string) (loginaccount *accountModel.Loginaccount, err error) {
  42. // LoginID
  43. if loginID, _ := strconv.Atoi(userName); loginID != 0 {
  44. loginaccount = &accountModel.Loginaccount{
  45. LOGINID: int64(loginID),
  46. PASSWORD: password,
  47. }
  48. if has, _ := global.M2A_DB.Get(loginaccount); has {
  49. return
  50. }
  51. }
  52. // LoginCode
  53. loginaccount = &accountModel.Loginaccount{
  54. LOGINCODE: userName,
  55. PASSWORD: password,
  56. }
  57. if has, _ := global.M2A_DB.Get(loginaccount); has {
  58. return
  59. }
  60. // 手机号码,需要AES加密
  61. key, _ := hex.DecodeString(utils.AESSecretKey)
  62. if mobileEncrypted, _ := utils.AESEncrypt([]byte(userName), key); mobileEncrypted != nil {
  63. loginaccount = &accountModel.Loginaccount{
  64. MOBILE: string(mobileEncrypted),
  65. PASSWORD: password,
  66. }
  67. if has, _ := global.M2A_DB.Get(loginaccount); has {
  68. return
  69. }
  70. }
  71. err = errors.New("错误的用户名或密码")
  72. return
  73. }
  74. // newSessionID 获取
  75. func newSessionID() int {
  76. mtx.Lock()
  77. curSessionID += 1
  78. mtx.Unlock()
  79. return curSessionID
  80. }
  81. // buildRedisLoginInfo 生成Token,并写入Redis
  82. func buildRedisLoginInfo(loginaccount accountModel.Loginaccount, addr string, group int) (token string, expiresAt int64, err error) {
  83. // 生成SessionID
  84. sessionID := newSessionID()
  85. // 生成本服务Token
  86. j := &utils.JWT{SigningKey: []byte(global.M2A_CONFIG.JWT.SigningKey)} // 唯一签名
  87. claims := j.CreateClaims(jwtRequest.BaseClaims{
  88. LoginID: int(loginaccount.LOGINID),
  89. SessionID: sessionID,
  90. })
  91. token, err = j.CreateToken(claims)
  92. if err != nil {
  93. global.M2A_LOG.Error("生成本服token失败", zap.Error(err))
  94. return
  95. }
  96. expiresAt = claims.RegisteredClaims.ExpiresAt.Unix()
  97. loginLogin := global.LoginRedis{
  98. LoginID: strconv.Itoa(int(loginaccount.LOGINID)),
  99. UserID: strconv.Itoa(int(loginaccount.USERID)),
  100. SessionID: strconv.Itoa(sessionID),
  101. Token: token,
  102. Group: strconv.Itoa(group),
  103. Addr: addr,
  104. }
  105. loginMap, err := loginLogin.ToMap()
  106. // loginMap := map[string]interface{}{
  107. // "LoginID": strconv.Itoa(int(loginaccount.LOGINID)),
  108. // "UserID": strconv.Itoa(int(loginaccount.USERID)),
  109. // "SessionID": strconv.Itoa(sessionID),
  110. // "Token": token,
  111. // "Group": strconv.Itoa(group),
  112. // "Addr": addr,
  113. // }
  114. if err != nil {
  115. global.M2A_LOG.Error("生成登录信息MAP失败", zap.Error(err))
  116. return
  117. }
  118. if err = j.SetRedisLogin(int(loginaccount.LOGINID), group, loginMap); err != nil {
  119. global.M2A_LOG.Error("Token写入Redis失败", zap.Error(err))
  120. return
  121. }
  122. // 生成旧登录服务Token
  123. // if err = j.SetOriRedisToken(int(loginaccount.LOGINID), group); err != nil {
  124. // // FIXME: 这里有类事务的回滚问题
  125. // global.M2A_LOG.Error("生成旧登录服务Token失败", zap.Error(err))
  126. // return
  127. // }
  128. return
  129. }