user_login.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. package controllers
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "eta/eta_api/models"
  6. "eta/eta_api/models/system"
  7. "eta/eta_api/services"
  8. "eta/eta_api/utils"
  9. "fmt"
  10. "github.com/mojocn/base64Captcha"
  11. "image/color"
  12. "strings"
  13. "time"
  14. )
  15. // UserLoginController 登录-无需Token
  16. type UserLoginController struct {
  17. BaseCommonController
  18. }
  19. // UserLoginAuthController 登录-需Token
  20. type UserLoginAuthController struct {
  21. BaseAuthController
  22. }
  23. // GenerateCaptcha
  24. // @Title 生成图形验证码
  25. // @Description 生成图形验证码
  26. // @Success 200 Ret=200 获取成功
  27. // @router /get_captcha [get]
  28. func (this *UserLoginController) GenerateCaptcha() {
  29. br := new(models.BaseResponse).Init()
  30. defer func() {
  31. if br.ErrMsg == "" {
  32. br.IsSendEmail = false
  33. }
  34. this.Data["json"] = br
  35. this.ServeJSON()
  36. }()
  37. //driver := base64Captcha.DefaultDriverDigit
  38. // 自定义验证码样式
  39. var driver base64Captcha.Driver
  40. driverString := base64Captcha.DriverString{
  41. Height: 60, //高度
  42. Width: 120, //宽度
  43. NoiseCount: 0, //干扰数
  44. ShowLineOptions: 2 | 4, //展示个数
  45. Length: 4, //长度
  46. //Source: "1234567890qwertyuioplkjhgfdsazxcvbnm", //验证码随机字符串来源
  47. Source: "1234567890", //验证码随机字符串来源
  48. BgColor: &color.RGBA{ // 背景颜色
  49. R: 0,
  50. G: 0,
  51. B: 0,
  52. A: 0,
  53. },
  54. Fonts: []string{"wqy-microhei.ttc"}, // 字体
  55. }
  56. driver = driverString.ConvertFonts()
  57. // 生成验证码
  58. store := services.CaptchaRedis{}
  59. captcha := base64Captcha.NewCaptcha(driver, store)
  60. id, b64s, err := captcha.Generate()
  61. if err != nil {
  62. br.Msg = "生成失败"
  63. br.ErrMsg = "生成验证码失败, Err: " + err.Error()
  64. return
  65. }
  66. type CaptchaResult struct {
  67. Id string
  68. Base64Blob string
  69. }
  70. res := new(CaptchaResult)
  71. res.Id = id
  72. res.Base64Blob = b64s
  73. br.Ret = 200
  74. br.Success = true
  75. br.Msg = "获取成功"
  76. br.Data = res
  77. }
  78. // GetVerifyCode
  79. // @Title 获取短信/邮箱验证码
  80. // @Description 获取短信/邮箱验证码
  81. // @Param request body VerifyCodeReq true "type json string"
  82. // @Success 200 Ret=200 获取成功
  83. // @router /verify_code [post]
  84. func (this *UserLoginController) GetVerifyCode() {
  85. br := new(models.BaseResponse).Init()
  86. defer func() {
  87. if br.ErrMsg == "" {
  88. br.IsSendEmail = false
  89. }
  90. this.Data["json"] = br
  91. this.ServeJSON()
  92. }()
  93. type VerifyCodeReq struct {
  94. VerifyType int `description:"验证方式: 1-手机号; 2-邮箱"`
  95. CaptchaId string `description:"验证码ID"`
  96. CaptchaCode string `description:"图形验证码"`
  97. Mobile string `description:"手机号"`
  98. Email string `description:"邮箱"`
  99. Source int `description:"来源:1-登录;2-异常登录校验;3-忘记密码"`
  100. }
  101. var req VerifyCodeReq
  102. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  103. if err != nil {
  104. br.Msg = "参数解析异常!"
  105. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  106. return
  107. }
  108. if req.VerifyType != 1 && req.VerifyType != 2 {
  109. br.Msg = "验证方式有误"
  110. br.ErrMsg = "验证方式有误"
  111. return
  112. }
  113. if req.Source != 1 && req.Source != 2 && req.Source != 3 {
  114. br.Msg = "来源有误"
  115. br.ErrMsg = "来源有误"
  116. return
  117. }
  118. // 忘记密码图形校验在前一步, 这一步不再校验图形验证码
  119. if req.Source != 3 {
  120. if req.CaptchaId == "" || req.CaptchaCode == "" {
  121. br.Msg = "请输入图形验证码"
  122. return
  123. }
  124. }
  125. if req.VerifyType == 1 && req.Mobile == "" {
  126. br.Msg = "请输入手机号"
  127. return
  128. }
  129. if req.VerifyType == 2 && req.Email == "" {
  130. br.Msg = "请输入邮箱"
  131. return
  132. }
  133. if req.Source != 3 {
  134. store := services.CaptchaRedis{}
  135. ok := store.Verify(req.CaptchaId, req.CaptchaCode, true)
  136. if !ok {
  137. br.Msg = "图形验证码错误, 请重新输入"
  138. return
  139. }
  140. }
  141. // 限制最多60s获取一次
  142. var lockKey string
  143. if req.VerifyType == 1 {
  144. lockKey = fmt.Sprint(utils.CaptchaCachePrefix, "lock:eta_", req.Mobile)
  145. }
  146. if req.VerifyType == 2 {
  147. lockKey = fmt.Sprint(utils.CaptchaCachePrefix, "lock:eta_", req.Email)
  148. }
  149. locked := utils.Rc.SetNX(lockKey, 1, time.Minute)
  150. if !locked {
  151. br.Msg = "请勿频繁发送"
  152. return
  153. }
  154. // 发送验证码
  155. sendRes := false
  156. if req.VerifyType == 1 {
  157. r, e := services.SendAdminMobileVerifyCode(req.Source, req.Mobile)
  158. if e != nil {
  159. br.Msg = "发送失败"
  160. br.ErrMsg = "发送短信验证码失败, Err: " + e.Error()
  161. return
  162. }
  163. sendRes = r
  164. }
  165. if req.VerifyType == 2 {
  166. r, e := services.SendAdminEmailVerifyCode(req.Source, req.Email)
  167. if e != nil {
  168. br.Msg = "发送失败"
  169. br.ErrMsg = "发送邮箱验证码失败, Err: " + e.Error()
  170. return
  171. }
  172. sendRes = r
  173. }
  174. if !sendRes {
  175. br.Msg = "发送失败"
  176. br.ErrMsg = "发送短信验证码失败"
  177. return
  178. }
  179. br.Ret = 200
  180. br.Success = true
  181. br.Msg = "发送成功"
  182. }
  183. // Login
  184. // @Title 用户登录
  185. // @Description 用户登录
  186. // @Param request body UserLoginReq true "type json string"
  187. // @Success 200 {object} models.LoginResp
  188. // @router /login [post]
  189. func (this *UserLoginController) Login() {
  190. br := new(models.BaseResponse).Init()
  191. defer func() {
  192. if br.ErrMsg != "" {
  193. br.IsSendEmail = false
  194. }
  195. this.Data["json"] = br
  196. this.ServeJSON()
  197. }()
  198. // 入参
  199. type UserLoginReq struct {
  200. LoginType int `description:"登录方式: 1-账号; 2-手机号; 3-邮箱"`
  201. AbnormalCheckType int `description:"异常登陆校验方式: 1-手机号; 2-邮箱"`
  202. Username string `description:"账号"`
  203. Password string `description:"密码"`
  204. Mobile string `description:"手机号"`
  205. Email string `description:"邮箱"`
  206. VerifyCode string `description:"验证码"`
  207. }
  208. var req UserLoginReq
  209. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  210. if err != nil {
  211. br.Msg = "参数解析异常!"
  212. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  213. return
  214. }
  215. req.Username = strings.TrimSpace(req.Username)
  216. req.Mobile = strings.TrimSpace(req.Mobile)
  217. if req.Mobile != "" {
  218. if !utils.ValidateMobileFormatat(req.Mobile) {
  219. br.Msg = "您的手机号输入有误, 请检查"
  220. return
  221. }
  222. }
  223. req.Email = strings.TrimSpace(req.Email)
  224. if req.Email != "" {
  225. if !utils.ValidateEmailFormatat(req.Email) {
  226. br.Msg = "您的邮箱输入有误, 请检查"
  227. return
  228. }
  229. }
  230. req.VerifyCode = strings.TrimSpace(req.VerifyCode)
  231. if req.LoginType != 1 && req.LoginType != 2 && req.LoginType != 3 {
  232. br.Msg = "登录方式有误"
  233. br.ErrMsg = fmt.Sprintf("登录方式有误, Type: %d", req.LoginType)
  234. return
  235. }
  236. sysUser := new(system.Admin)
  237. // 账号密码登录
  238. if req.LoginType == 1 {
  239. if req.Username == "" {
  240. br.Msg = "请输入账号"
  241. return
  242. }
  243. if req.Password == "" {
  244. br.Msg = "请输入密码"
  245. return
  246. }
  247. // 判断账号是否为异常登录
  248. abnormalKey := fmt.Sprint(utils.CACHE_ABNORMAL_LOGIN, req.Username)
  249. isAbnormal, _ := utils.Rc.RedisString(abnormalKey)
  250. if isAbnormal != "" {
  251. if req.AbnormalCheckType != 1 && req.AbnormalCheckType != 2 {
  252. br.Msg = "账号异常, 请进行手机号/邮箱校验"
  253. br.ErrMsg = fmt.Sprintf("账号异常, 请进行手机号/邮箱校验, CheckType: %d", req.AbnormalCheckType)
  254. return
  255. }
  256. recordCond := ` AND source = ?`
  257. recordPars := make([]interface{}, 0)
  258. recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceAbnormal)
  259. if req.AbnormalCheckType == 1 {
  260. if req.Mobile == "" {
  261. br.Msg = "请输入手机号"
  262. return
  263. }
  264. if !utils.ValidateMobileFormatat(req.Mobile) {
  265. br.Msg = "您的手机号输入有误, 请检查"
  266. return
  267. }
  268. recordCond += ` AND mobile = ?`
  269. recordPars = append(recordPars, req.Mobile)
  270. }
  271. if req.AbnormalCheckType == 2 {
  272. if req.Email == "" {
  273. br.Msg = "请输入邮箱"
  274. return
  275. }
  276. if !utils.ValidateEmailFormatat(req.Email) {
  277. br.Msg = "您的邮箱输入有误, 请检查"
  278. return
  279. }
  280. recordCond += ` AND email = ?`
  281. recordPars = append(recordPars, req.Email)
  282. }
  283. if req.VerifyCode == "" {
  284. br.Msg = "请输入验证码"
  285. return
  286. }
  287. expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
  288. recordCond += ` AND code = ? AND expired_time <= ?`
  289. recordPars = append(recordPars, req.VerifyCode, expiredTime)
  290. // 校验验证码
  291. recordOb := new(system.AdminVerifyCodeRecord)
  292. _, e := recordOb.GetItemByCondition(recordCond, recordPars)
  293. if e != nil {
  294. if e.Error() == utils.ErrNoRow() {
  295. br.Msg = "验证码错误, 请重新输入"
  296. return
  297. }
  298. br.Msg = "验证码错误, 请重新输入"
  299. br.ErrMsg = "获取异常登陆验证码失败, Err: " + e.Error()
  300. return
  301. }
  302. }
  303. // 账号密码校验
  304. errPassKey := fmt.Sprint(utils.CACHE_LOGIN_ERR_PASS, req.Username)
  305. accountUser, e := system.CheckSysUser(req.Username, req.Password)
  306. if e != nil {
  307. if e.Error() == utils.ErrNoRow() {
  308. br.Msg = "登录失败, 账号或密码错误"
  309. if isAbnormal != "" {
  310. return
  311. }
  312. // 错误密码计数, 超过6次标记异常
  313. if !utils.Rc.IsExist(errPassKey) {
  314. _ = utils.Rc.Put(errPassKey, 1, utils.GetTodayLastSecond())
  315. return
  316. }
  317. errNum, _ := utils.Rc.RedisInt(errPassKey)
  318. errNum += 1
  319. if errNum >= 6 {
  320. br.Ret = models.BaseRespCodeAbnormalLogin
  321. // 标记异常登录, 重置计数
  322. _ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
  323. _ = utils.Rc.Delete(errPassKey)
  324. return
  325. }
  326. _ = utils.Rc.Put(errPassKey, errNum, utils.GetTodayLastSecond())
  327. return
  328. }
  329. br.Msg = "登录失败, 账号或密码错误"
  330. br.ErrMsg = "登录失败, Err:" + e.Error()
  331. return
  332. }
  333. if accountUser.Enabled == 0 {
  334. br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
  335. br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录账号: %s, 账户名称: %s", accountUser.AdminName, accountUser.RealName)
  336. return
  337. }
  338. // 异常登录-是否登录间隔大于60天
  339. if isAbnormal == "" {
  340. abnormalTime := time.Now().AddDate(0, 0, -60)
  341. lastLogin, _ := time.ParseInLocation(utils.FormatDateTime, accountUser.LastLoginTime, time.Local)
  342. if !lastLogin.IsZero() && lastLogin.Before(abnormalTime) {
  343. br.Msg = "请进行异常登录校验"
  344. br.Ret = models.BaseRespCodeAbnormalLogin
  345. // 标记异常登录
  346. _ = utils.Rc.Put(abnormalKey, "true", utils.GetTodayLastSecond())
  347. return
  348. }
  349. }
  350. // 登录成功, 清除异常标记
  351. _ = utils.Rc.Delete(abnormalKey)
  352. _ = utils.Rc.Delete(errPassKey)
  353. sysUser = accountUser
  354. }
  355. // 手机号
  356. if req.LoginType == 2 {
  357. if req.Mobile == "" {
  358. br.Msg = "请输入手机号"
  359. return
  360. }
  361. if !utils.ValidateMobileFormatat(req.Mobile) {
  362. br.Msg = "您的手机号输入有误, 请检查"
  363. return
  364. }
  365. if req.VerifyCode == "" {
  366. br.Msg = "请输入验证码"
  367. return
  368. }
  369. expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
  370. recordCond := ` AND source = ? AND mobile = ? AND code = ? AND expired_time <= ?`
  371. recordPars := make([]interface{}, 0)
  372. recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceLogin, req.Mobile, req.VerifyCode, expiredTime)
  373. recordOb := new(system.AdminVerifyCodeRecord)
  374. _, e := recordOb.GetItemByCondition(recordCond, recordPars)
  375. if e != nil {
  376. if e.Error() == utils.ErrNoRow() {
  377. br.Msg = "验证码错误, 请重新输入"
  378. return
  379. }
  380. br.Msg = "验证码错误, 请重新输入"
  381. br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
  382. return
  383. }
  384. mobileUser, e := system.GetSysUserByMobile(req.Mobile)
  385. if e != nil {
  386. if e.Error() == utils.ErrNoRow() {
  387. br.Msg = "您的手机号未绑定账号, 请检查"
  388. return
  389. }
  390. br.Msg = "您的手机号未绑定账号, 请检查"
  391. br.ErrMsg = "手机号获取用户失败, Err:" + e.Error()
  392. return
  393. }
  394. if mobileUser.Enabled == 0 {
  395. br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
  396. br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录手机号: %s", req.Mobile)
  397. return
  398. }
  399. sysUser = mobileUser
  400. }
  401. // 邮箱登录
  402. if req.LoginType == 3 {
  403. if req.Email == "" {
  404. br.Msg = "请输入邮箱"
  405. return
  406. }
  407. if !utils.ValidateEmailFormatat(req.Email) {
  408. br.Msg = "您的邮箱输入有误, 请检查"
  409. return
  410. }
  411. if req.VerifyCode == "" {
  412. br.Msg = "请输入验证码"
  413. return
  414. }
  415. expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
  416. recordCond := ` AND source = ? AND email = ? AND code = ? AND expired_time <= ?`
  417. recordPars := make([]interface{}, 0)
  418. recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceLogin, req.Email, req.VerifyCode, expiredTime)
  419. recordOb := new(system.AdminVerifyCodeRecord)
  420. _, e := recordOb.GetItemByCondition(recordCond, recordPars)
  421. if e != nil {
  422. if e.Error() == utils.ErrNoRow() {
  423. br.Msg = "验证码错误, 请重新输入"
  424. return
  425. }
  426. br.Msg = "验证码错误, 请重新输入"
  427. br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
  428. return
  429. }
  430. emailUser, e := system.GetSysUserByEmail(req.Email)
  431. if e != nil {
  432. if e.Error() == utils.ErrNoRow() {
  433. br.Msg = "您的邮箱未绑定账号, 请检查"
  434. return
  435. }
  436. br.Msg = "您的邮箱未绑定账号, 请检查"
  437. br.ErrMsg = "邮箱获取用户失败, Err:" + e.Error()
  438. return
  439. }
  440. if emailUser.Enabled == 0 {
  441. br.Msg = "您的账号已被禁用, 如需登录, 请联系管理员"
  442. br.ErrMsg = fmt.Sprintf("账号已被禁用, 登录邮箱: %s", req.Email)
  443. return
  444. }
  445. sysUser = emailUser
  446. }
  447. account := utils.MD5(sysUser.AdminName)
  448. token := utils.GenToken(account)
  449. sysSession := new(system.SysSession)
  450. sysSession.UserName = req.Username
  451. sysSession.SysUserId = sysUser.AdminId
  452. sysSession.ExpiredTime = time.Now().AddDate(0, 0, 90)
  453. sysSession.IsRemember = 0 // 均需要做过期校验
  454. sysSession.CreatedTime = time.Now()
  455. sysSession.LastUpdatedTime = time.Now()
  456. sysSession.AccessToken = token
  457. if e := system.AddSysSession(sysSession); e != nil {
  458. br.Msg = "登录失败"
  459. br.ErrMsg = "新增session信息失败, Err:" + e.Error()
  460. return
  461. }
  462. // 修改最后登录时间
  463. {
  464. sysUser.LastLoginTime = time.Now().Format(utils.FormatDateTime)
  465. sysUser.LastUpdatedTime = time.Now().Format(utils.FormatDateTime)
  466. _ = sysUser.Update([]string{"LastLoginTime", "LastUpdatedTime"})
  467. }
  468. resp := new(system.LoginResp)
  469. resp.Authorization = token
  470. resp.Authorization = "authorization=" + token + "$account=" + account
  471. resp.RealName = sysUser.RealName
  472. resp.AdminName = sysUser.AdminName
  473. resp.RoleName = sysUser.RoleName
  474. resp.SysRoleTypeCode = sysUser.RoleTypeCode //系统角色编码
  475. resp.RoleTypeCode = sysUser.RoleTypeCode
  476. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_GROUP {
  477. resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
  478. }
  479. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_TEAM {
  480. resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
  481. }
  482. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_FICC_DEPARTMENT {
  483. resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
  484. }
  485. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_GROUP {
  486. resp.RoleTypeCode = utils.ROLE_TYPE_CODE_RAI_SELLER
  487. }
  488. if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_RAI_DEPARTMENT {
  489. resp.RoleTypeCode = utils.ROLE_TYPE_CODE_RAI_SELLER
  490. }
  491. if sysUser.RoleName == utils.ROLE_NAME_FICC_DIRECTOR {
  492. resp.RoleTypeCode = utils.ROLE_TYPE_CODE_FICC_SELLER
  493. }
  494. resp.AdminId = sysUser.AdminId
  495. var productName string
  496. productId := services.GetProductId(sysUser.RoleTypeCode)
  497. if productId == 1 {
  498. productName = utils.COMPANY_PRODUCT_FICC_NAME
  499. } else if productId == 2 {
  500. productName = utils.COMPANY_PRODUCT_RAI_NAME
  501. } else {
  502. productName = "admin"
  503. }
  504. resp.ProductName = productName
  505. resp.Authority = sysUser.Authority
  506. // 设置redis缓存
  507. {
  508. // 获取不可信的登录态,并将该登录态重置掉,不允许多次登录
  509. noTrustLoginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN_NO_TRUST, sysUser.AdminId)
  510. noTrustLoginId, _ := utils.Rc.RedisString(noTrustLoginKey)
  511. if noTrustLoginId != `` { // 如果存在不可信设备,那么将其下架
  512. oldNoTrustLoginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN, noTrustLoginId)
  513. _ = utils.Rc.Put(oldNoTrustLoginKey, "0", 30*time.Minute)
  514. }
  515. // 如果当前是不可信设备,那么将其加入到不可信名单
  516. loginKey := fmt.Sprint(utils.CACHE_ACCESS_TOKEN_LOGIN, sysSession.Id)
  517. _ = utils.Rc.Put(loginKey, "1", 30*time.Minute)
  518. _ = utils.Rc.Put(noTrustLoginKey, sysSession.Id, 30*time.Minute)
  519. }
  520. // 新增登录记录
  521. go func() {
  522. record := new(system.SysUserLoginRecord)
  523. record.Uid = sysUser.AdminId
  524. record.UserName = req.Username
  525. record.Ip = this.Ctx.Input.IP()
  526. record.Stage = "login"
  527. record.CreateTime = time.Now()
  528. _ = system.AddSysUserLoginRecord(record)
  529. }()
  530. br.Data = resp
  531. br.Ret = 200
  532. br.Success = true
  533. br.Msg = "登录成功"
  534. }
  535. // ForgetAccountGet
  536. // @Title 忘记密码-账号校验
  537. // @Description 忘记密码-账号校验
  538. // @Param request body ForgetAccountGetReq true "type json string"
  539. // @Success 200 Ret=200 获取成功
  540. // @router /forget/account_get [post]
  541. func (this *UserLoginController) ForgetAccountGet() {
  542. br := new(models.BaseResponse).Init()
  543. defer func() {
  544. if br.ErrMsg == "" {
  545. br.IsSendEmail = false
  546. }
  547. this.Data["json"] = br
  548. this.ServeJSON()
  549. }()
  550. type ForgetAccountGetReq struct {
  551. CaptchaId string `description:"验证码ID"`
  552. CaptchaCode string `description:"图形验证码"`
  553. UserName string `description:"用户名"`
  554. }
  555. var req ForgetAccountGetReq
  556. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  557. if err != nil {
  558. br.Msg = "参数解析异常!"
  559. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  560. return
  561. }
  562. req.UserName = strings.TrimSpace(req.UserName)
  563. if req.UserName == "" {
  564. br.Msg = "请输入账号"
  565. return
  566. }
  567. if req.CaptchaId == "" || req.CaptchaCode == "" {
  568. br.Msg = "请输入图形验证码"
  569. return
  570. }
  571. store := services.CaptchaRedis{}
  572. ok := store.Verify(req.CaptchaId, req.CaptchaCode, true)
  573. if !ok {
  574. br.Msg = "验证码错误, 请重新输入"
  575. return
  576. }
  577. sysUser, e := system.GetSysUserByAdminName(req.UserName)
  578. if e != nil {
  579. if e.Error() == utils.ErrNoRow() {
  580. br.Msg = "用户不存在, 请检查"
  581. return
  582. }
  583. br.Msg = "账号错误, 请重新输入"
  584. br.ErrMsg = "用户名获取用户失败, Err: " + e.Error()
  585. return
  586. }
  587. type ForgetAccountCheckResp struct {
  588. Mobile string `description:"手机号"`
  589. Email string `description:"邮箱"`
  590. }
  591. resp := ForgetAccountCheckResp{
  592. Mobile: sysUser.Mobile,
  593. Email: sysUser.Email,
  594. }
  595. br.Data = resp
  596. br.Ret = 200
  597. br.Success = true
  598. br.Msg = "获取成功"
  599. }
  600. // ForgetCodeVerify
  601. // @Title 忘记密码-验证码校验
  602. // @Description 忘记密码-验证码校验
  603. // @Param request body ForgetCodeVerifyReq true "type json string"
  604. // @Success 200 Ret=200 获取成功
  605. // @router /forget/code_verify [post]
  606. func (this *UserLoginController) ForgetCodeVerify() {
  607. br := new(models.BaseResponse).Init()
  608. defer func() {
  609. if br.ErrMsg == "" {
  610. br.IsSendEmail = false
  611. }
  612. this.Data["json"] = br
  613. this.ServeJSON()
  614. }()
  615. type ForgetCodeVerifyReq struct {
  616. FindType int `description:"密码找回方式: 1-手机号; 2-邮箱"`
  617. VerifyCode string `description:"验证码"`
  618. UserName string `description:"用户名"`
  619. Mobile string `description:"手机号"`
  620. Email string `description:"邮箱"`
  621. }
  622. var req ForgetCodeVerifyReq
  623. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  624. if err != nil {
  625. br.Msg = "参数解析异常!"
  626. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  627. return
  628. }
  629. req.UserName = strings.TrimSpace(req.UserName)
  630. if req.UserName == "" {
  631. br.Msg = "请输入账号"
  632. return
  633. }
  634. if req.VerifyCode == "" {
  635. br.Msg = "请输入验证码"
  636. return
  637. }
  638. // 手机号找回
  639. var verifyRes bool
  640. if req.FindType == 1 {
  641. req.Mobile = strings.TrimSpace(req.Mobile)
  642. if req.Mobile == "" {
  643. br.Msg = "请输入手机号"
  644. return
  645. }
  646. if !utils.ValidateMobileFormatat(req.Mobile) {
  647. br.Msg = "您的手机号输入有误, 请检查"
  648. return
  649. }
  650. expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
  651. recordCond := ` AND source = ? AND mobile = ? AND code = ? AND expired_time <= ?`
  652. recordPars := make([]interface{}, 0)
  653. recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceForget, req.Mobile, req.VerifyCode, expiredTime)
  654. recordOb := new(system.AdminVerifyCodeRecord)
  655. _, e := recordOb.GetItemByCondition(recordCond, recordPars)
  656. if e != nil {
  657. if e.Error() == utils.ErrNoRow() {
  658. br.Msg = "验证码错误, 请重新输入"
  659. return
  660. }
  661. br.Msg = "验证码错误, 请重新输入"
  662. br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
  663. return
  664. }
  665. verifyRes = true
  666. }
  667. // 邮箱找回
  668. if req.FindType == 2 {
  669. req.Email = strings.TrimSpace(req.Email)
  670. if req.Email == "" {
  671. br.Msg = "请输入邮箱"
  672. return
  673. }
  674. if !utils.ValidateEmailFormatat(req.Email) {
  675. br.Msg = "您的邮箱输入有误, 请检查"
  676. return
  677. }
  678. expiredTime := time.Now().Add(utils.VerifyCodeExpireMinute * time.Minute).Format(utils.FormatDateTime)
  679. recordCond := ` AND source = ? AND email = ? AND code = ? AND expired_time <= ?`
  680. recordPars := make([]interface{}, 0)
  681. recordPars = append(recordPars, system.AdminVerifyCodeRecordSourceForget, req.Email, req.VerifyCode, expiredTime)
  682. recordOb := new(system.AdminVerifyCodeRecord)
  683. _, e := recordOb.GetItemByCondition(recordCond, recordPars)
  684. if e != nil {
  685. if e.Error() == utils.ErrNoRow() {
  686. br.Msg = "验证码错误, 请重新输入"
  687. return
  688. }
  689. br.Msg = "验证码错误, 请重新输入"
  690. br.ErrMsg = "获取手机号登陆验证码失败, Err: " + e.Error()
  691. return
  692. }
  693. verifyRes = true
  694. }
  695. if verifyRes {
  696. successKey := fmt.Sprint(utils.CACHE_FIND_PASS_VERIFY, req.UserName)
  697. _ = utils.Rc.Put(successKey, "true", utils.GetTodayLastSecond())
  698. }
  699. br.Data = verifyRes
  700. br.Ret = 200
  701. br.Success = true
  702. br.Msg = "操作成功"
  703. }
  704. // ForgetResetPass
  705. // @Title 忘记密码-重置密码
  706. // @Description 忘记密码-重置密码
  707. // @Param request body ForgetResetPassReq true "type json string"
  708. // @Success 200 Ret=200 获取成功
  709. // @router /forget/reset_pass [post]
  710. func (this *UserLoginController) ForgetResetPass() {
  711. br := new(models.BaseResponse).Init()
  712. defer func() {
  713. if br.ErrMsg == "" {
  714. br.IsSendEmail = false
  715. }
  716. this.Data["json"] = br
  717. this.ServeJSON()
  718. }()
  719. type ForgetResetPassReq struct {
  720. UserName string `description:"用户名"`
  721. Password string `description:"密码"`
  722. RePassword string `description:"重复密码"`
  723. }
  724. var req ForgetResetPassReq
  725. err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
  726. if err != nil {
  727. br.Msg = "参数解析异常!"
  728. br.ErrMsg = "参数解析失败,Err:" + err.Error()
  729. return
  730. }
  731. req.UserName = strings.TrimSpace(req.UserName)
  732. if req.UserName == "" {
  733. br.Msg = "请输入账号"
  734. return
  735. }
  736. req.Password = strings.TrimSpace(req.Password)
  737. if req.Password == "" {
  738. br.Msg = "请输入新密码"
  739. return
  740. }
  741. req.RePassword = strings.TrimSpace(req.RePassword)
  742. if req.RePassword == "" {
  743. br.Msg = "请确认新密码"
  744. return
  745. }
  746. if req.Password != req.RePassword {
  747. br.Msg = "两次密码输入不一致, 请检查"
  748. return
  749. }
  750. // 接上一步-验证码校验成功后才允许修改
  751. successKey := fmt.Sprint(utils.CACHE_FIND_PASS_VERIFY, req.UserName)
  752. verifyOk, _ := utils.Rc.RedisString(successKey)
  753. if verifyOk != "true" {
  754. br.Msg = "验证码校验失效, 请重新验证"
  755. br.ErrMsg = "重置密码异常, 验证码校验已失效"
  756. return
  757. }
  758. sysUser, e := system.GetSysAdminByName(req.UserName)
  759. if e != nil {
  760. if e.Error() == utils.ErrNoRow() {
  761. br.Msg = "用户不存在, 请检查"
  762. return
  763. }
  764. br.Msg = "操作失败"
  765. br.ErrMsg = "密码找回获取用户失败, Err:" + e.Error()
  766. return
  767. }
  768. b, e := base64.StdEncoding.DecodeString(req.Password)
  769. if e != nil {
  770. br.Msg = "操作失败"
  771. br.ErrMsg = "解析密码失败, Err:" + e.Error()
  772. return
  773. }
  774. pwd := string(b)
  775. pwd = utils.MD5(pwd)
  776. sysUser.Password = pwd
  777. sysUser.LastUpdatedPasswordTime = time.Now().Format(utils.FormatDateTime)
  778. // 重置密码后更新一下登录时间, 不然账号密码登录如果超过60天还会被异常校验再校验一次, 影响体验
  779. sysUser.LastLoginTime = time.Now().Format(utils.FormatDateTime)
  780. sysUser.LastUpdatedTime = time.Now().Format(utils.FormatDateTime)
  781. if e = sysUser.Update([]string{"Password", "LastUpdatedPasswordTime", "LastLoginTime", "LastUpdatedTime"}); e != nil {
  782. br.Msg = "操作失败"
  783. br.ErrMsg = "更新密码失败, Err: " + e.Error()
  784. return
  785. }
  786. _ = utils.Rc.Delete(successKey)
  787. // 同步ETA用户缓存
  788. var syncData system.SyncAdminData
  789. syncData.Source = utils.SOURCE_CRM_FLAG
  790. syncData.AdminName = sysUser.AdminName
  791. _ = utils.Rc.LPush(utils.CACHE_SYNC_ADMIN, syncData)
  792. br.Data = true
  793. br.Ret = 200
  794. br.Success = true
  795. br.Msg = "操作成功"
  796. }