login.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. package admin
  2. import (
  3. "fmt"
  4. "github.com/gin-gonic/gin"
  5. "github.com/lejianwen/rustdesk-api/v2/global"
  6. "github.com/lejianwen/rustdesk-api/v2/http/controller/api"
  7. "github.com/lejianwen/rustdesk-api/v2/http/request/admin"
  8. apiReq "github.com/lejianwen/rustdesk-api/v2/http/request/api"
  9. "github.com/lejianwen/rustdesk-api/v2/http/response"
  10. adResp "github.com/lejianwen/rustdesk-api/v2/http/response/admin"
  11. "github.com/lejianwen/rustdesk-api/v2/model"
  12. "github.com/lejianwen/rustdesk-api/v2/service"
  13. )
  14. type Login struct {
  15. }
  16. // Login 登录
  17. // @Tags 登录
  18. // @Summary 登录
  19. // @Description 登录
  20. // @Accept json
  21. // @Produce json
  22. // @Param body body admin.Login true "登录信息"
  23. // @Success 200 {object} response.Response{data=adResp.LoginPayload}
  24. // @Failure 500 {object} response.Response
  25. // @Router /admin/login [post]
  26. // @Security token
  27. func (ct *Login) Login(c *gin.Context) {
  28. if global.Config.App.DisablePwdLogin {
  29. response.Fail(c, 101, response.TranslateMsg(c, "PwdLoginDisabled"))
  30. return
  31. }
  32. // 检查登录限制
  33. loginLimiter := global.LoginLimiter
  34. clientIp := c.ClientIP()
  35. _, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
  36. f := &admin.Login{}
  37. err := c.ShouldBindJSON(f)
  38. if err != nil {
  39. loginLimiter.RecordFailedAttempt(clientIp)
  40. global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), clientIp))
  41. response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
  42. return
  43. }
  44. errList := global.Validator.ValidStruct(c, f)
  45. if len(errList) > 0 {
  46. loginLimiter.RecordFailedAttempt(clientIp)
  47. global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "ParamsError", c.RemoteIP(), clientIp))
  48. response.Fail(c, 101, errList[0])
  49. return
  50. }
  51. // 检查是否需要验证码
  52. if needCaptcha {
  53. if f.Captcha == "" || !loginLimiter.VerifyCaptcha(clientIp, f.Captcha) {
  54. response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError"))
  55. return
  56. }
  57. }
  58. u := service.AllService.UserService.InfoByUsernamePassword(f.Username, f.Password)
  59. if u.Id == 0 {
  60. global.Logger.Warn(fmt.Sprintf("Login Fail: %s %s %s", "UsernameOrPasswordError", c.RemoteIP(), clientIp))
  61. loginLimiter.RecordFailedAttempt(clientIp)
  62. // 移除验证码,重新生成
  63. loginLimiter.RemoveCaptcha(clientIp)
  64. if _, needCaptcha = loginLimiter.CheckSecurityStatus(clientIp); needCaptcha {
  65. response.Fail(c, 110, response.TranslateMsg(c, "UsernameOrPasswordError"))
  66. } else {
  67. response.Fail(c, 101, response.TranslateMsg(c, "UsernameOrPasswordError"))
  68. }
  69. return
  70. }
  71. if !service.AllService.UserService.CheckUserEnable(u) {
  72. if needCaptcha {
  73. loginLimiter.RemoveCaptcha(clientIp)
  74. response.Fail(c, 110, response.TranslateMsg(c, "UserDisabled"))
  75. return
  76. }
  77. response.Fail(c, 101, response.TranslateMsg(c, "UserDisabled"))
  78. return
  79. }
  80. ut := service.AllService.UserService.Login(u, &model.LoginLog{
  81. UserId: u.Id,
  82. Client: model.LoginLogClientWebAdmin,
  83. Uuid: "", //must be empty
  84. Ip: clientIp,
  85. Type: model.LoginLogTypeAccount,
  86. Platform: f.Platform,
  87. })
  88. // 登录成功,清除登录限制
  89. loginLimiter.RemoveAttempts(clientIp)
  90. responseLoginSuccess(c, u, ut.Token)
  91. }
  92. func (ct *Login) Captcha(c *gin.Context) {
  93. loginLimiter := global.LoginLimiter
  94. clientIp := c.ClientIP()
  95. banned, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
  96. if banned {
  97. response.Fail(c, 101, response.TranslateMsg(c, "LoginBanned"))
  98. return
  99. }
  100. if !needCaptcha {
  101. response.Fail(c, 101, response.TranslateMsg(c, "NoCaptchaRequired"))
  102. return
  103. }
  104. err, captcha := loginLimiter.RequireCaptcha(clientIp)
  105. if err != nil {
  106. response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError")+err.Error())
  107. return
  108. }
  109. err, b64 := loginLimiter.DrawCaptcha(captcha.Content)
  110. if err != nil {
  111. response.Fail(c, 101, response.TranslateMsg(c, "CaptchaError")+err.Error())
  112. return
  113. }
  114. response.Success(c, gin.H{
  115. "captcha": gin.H{
  116. "b64": b64,
  117. },
  118. })
  119. }
  120. // Logout 登出
  121. // @Tags 登录
  122. // @Summary 登出
  123. // @Description 登出
  124. // @Accept json
  125. // @Produce json
  126. // @Success 200 {object} response.Response
  127. // @Failure 500 {object} response.Response
  128. // @Router /admin/logout [post]
  129. func (ct *Login) Logout(c *gin.Context) {
  130. u := service.AllService.UserService.CurUser(c)
  131. token, ok := c.Get("token")
  132. if ok {
  133. service.AllService.UserService.Logout(u, token.(string))
  134. }
  135. response.Success(c, nil)
  136. }
  137. // LoginOptions
  138. // @Tags 登录
  139. // @Summary 登录选项
  140. // @Description 登录选项
  141. // @Accept json
  142. // @Produce json
  143. // @Success 200 {object} []string
  144. // @Failure 500 {object} response.ErrorResponse
  145. // @Router /admin/login-options [post]
  146. func (ct *Login) LoginOptions(c *gin.Context) {
  147. loginLimiter := global.LoginLimiter
  148. clientIp := c.ClientIP()
  149. banned, needCaptcha := loginLimiter.CheckSecurityStatus(clientIp)
  150. if banned {
  151. response.Fail(c, 101, response.TranslateMsg(c, "LoginBanned"))
  152. return
  153. }
  154. ops := service.AllService.OauthService.GetOauthProviders()
  155. response.Success(c, gin.H{
  156. "ops": ops,
  157. "register": global.Config.App.Register,
  158. "need_captcha": needCaptcha,
  159. })
  160. }
  161. // OidcAuth
  162. // @Tags Oauth
  163. // @Summary OidcAuth
  164. // @Description OidcAuth
  165. // @Accept json
  166. // @Produce json
  167. // @Router /admin/oidc/auth [post]
  168. func (ct *Login) OidcAuth(c *gin.Context) {
  169. // o := &api.Oauth{}
  170. // o.OidcAuth(c)
  171. f := &apiReq.OidcAuthRequest{}
  172. err := c.ShouldBindJSON(f)
  173. if err != nil {
  174. response.Fail(c, 101, response.TranslateMsg(c, "ParamsError")+err.Error())
  175. return
  176. }
  177. err, state, verifier, nonce, url := service.AllService.OauthService.BeginAuth(f.Op)
  178. if err != nil {
  179. response.Error(c, response.TranslateMsg(c, err.Error()))
  180. return
  181. }
  182. service.AllService.OauthService.SetOauthCache(state, &service.OauthCacheItem{
  183. Action: service.OauthActionTypeLogin,
  184. Op: f.Op,
  185. Id: f.Id,
  186. DeviceType: "webadmin",
  187. // DeviceOs: ct.Platform(c),
  188. DeviceOs: f.DeviceInfo.Os,
  189. Uuid: f.Uuid,
  190. Verifier: verifier,
  191. Nonce: nonce,
  192. }, 5*60)
  193. response.Success(c, gin.H{
  194. "code": state,
  195. "url": url,
  196. })
  197. }
  198. // OidcAuthQuery
  199. // @Tags Oauth
  200. // @Summary OidcAuthQuery
  201. // @Description OidcAuthQuery
  202. // @Accept json
  203. // @Produce json
  204. // @Success 200 {object} response.Response{data=adResp.LoginPayload}
  205. // @Failure 500 {object} response.Response
  206. // @Router /admin/oidc/auth-query [get]
  207. func (ct *Login) OidcAuthQuery(c *gin.Context) {
  208. o := &api.Oauth{}
  209. u, ut := o.OidcAuthQueryPre(c)
  210. if ut == nil {
  211. return
  212. }
  213. responseLoginSuccess(c, u, ut.Token)
  214. }
  215. func responseLoginSuccess(c *gin.Context, u *model.User, token string) {
  216. lp := &adResp.LoginPayload{}
  217. lp.FromUser(u)
  218. lp.Token = token
  219. lp.RouteNames = service.AllService.UserService.RouteNames(u)
  220. response.Success(c, lp)
  221. }