token.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. package controller
  2. import (
  3. "fmt"
  4. "github.com/gin-gonic/gin"
  5. "github.com/golang-jwt/jwt"
  6. "github.com/mojocn/base64Captcha"
  7. "github.com/satori/go.uuid"
  8. "iot_manager_service/app/middleware"
  9. "iot_manager_service/app/system/dao"
  10. "iot_manager_service/app/system/service"
  11. "time"
  12. "iot_manager_service/app/system/model"
  13. "iot_manager_service/config"
  14. "iot_manager_service/util"
  15. "net/http"
  16. "strings"
  17. )
  18. var Auth = new(auth)
  19. type auth struct{}
  20. var driver = &base64Captcha.DriverString{
  21. Height: 48,
  22. Width: 130,
  23. NoiseCount: 100,
  24. ShowLineOptions: 2,
  25. Length: 5,
  26. BgColor: nil,
  27. }
  28. func (c *auth) Token(ctx *gin.Context) {
  29. tenantId := ctx.Query("tenantId")
  30. userName := ctx.Query("username")
  31. password := ctx.Query("password")
  32. grantType := ctx.Query("grant_type")
  33. refreshToken := ctx.Query("refresh_token")
  34. // 校验连续登录失败次数
  35. checkLock()
  36. userType := ctx.GetHeader(model.UserTypeHeaderKey)
  37. token := model.Token{
  38. TenantId: tenantId,
  39. UserName: userName,
  40. Password: password,
  41. GrantType: grantType,
  42. RefreshToken: refreshToken,
  43. UserType: userType,
  44. }
  45. var userInfo *model.UserInfo
  46. var err *util.Errors
  47. if grantType == "captcha" {
  48. userInfo, err = captchaGrant(token, ctx)
  49. if err != nil {
  50. ctx.JSON(http.StatusOK, err)
  51. return
  52. }
  53. } else if grantType == "refresh_token" {
  54. userInfo, err = refreshGrant(token)
  55. if err != nil {
  56. ctx.JSON(http.StatusOK, err)
  57. return
  58. }
  59. }
  60. if userInfo == nil || userInfo.User == nil {
  61. ctx.JSON(http.StatusOK, util.NormalResponse(http.StatusBadRequest, model.UserNotFound, nil))
  62. return
  63. }
  64. if len(userInfo.Roles) == 0 {
  65. ctx.JSON(http.StatusOK, util.NormalResponse(http.StatusBadRequest, model.UserHasNoRole, nil))
  66. return
  67. }
  68. // access token过期时间2小时
  69. random := util.RandomString(8)
  70. jwtToken, e := middleware.GetAccessToken(userInfo.ID, userInfo.RoleId, userInfo.TenantId, userInfo.Account, random)
  71. if e != nil {
  72. ctx.JSON(http.StatusOK, util.NormalResponse(http.StatusBadRequest, e.Error(), nil))
  73. return
  74. }
  75. // redis记录缓存2小时
  76. util.Redis.Set(getAccessTokenKey(userInfo.TenantId, userInfo.ID, random), jwtToken, 2*time.Hour)
  77. ctx.JSON(http.StatusOK, model.RspToken{
  78. TenantId: userInfo.TenantId,
  79. UserId: userInfo.ID,
  80. RoleId: userInfo.RoleId,
  81. OauthId: userInfo.OauthId,
  82. Account: userInfo.Account,
  83. UserName: userInfo.Name,
  84. NickName: userInfo.RealName,
  85. RoleName: userInfo.Roles[0],
  86. Avatar: userInfo.Avatar,
  87. AccessToken: jwtToken,
  88. RefreshToken: getRefreshToken(*userInfo),
  89. TokenType: model.BEARER,
  90. ExpiresIn: 7200,
  91. License: "",
  92. })
  93. }
  94. func (c *auth) Logout(ctx *gin.Context) {
  95. value, isExist := ctx.Get(middleware.Authorization)
  96. if !isExist || value == nil {
  97. ctx.JSON(http.StatusUnauthorized, util.NormalResponse(http.StatusUnauthorized, "", nil))
  98. return
  99. }
  100. jwtToken := value.(*middleware.JwtToken)
  101. _ = util.Redis.Del(getAccessTokenKey(jwtToken.TenantId, jwtToken.UserId, jwtToken.Random)).Err()
  102. //todo 操作记录
  103. ctx.JSON(http.StatusOK, util.SuccessResponse("", nil))
  104. }
  105. func (c *auth) Captcha(ctx *gin.Context) {
  106. id := uuid.NewV1().String()
  107. code := util.RandomString2(5)
  108. gotItem, _ := driver.DrawCaptcha(code)
  109. image := gotItem.EncodeB64string()
  110. rsp := model.RspCaptcha{
  111. Key: id,
  112. Image: image,
  113. }
  114. util.Redis.Set(getCaptchaKey(id), code, 5*time.Minute)
  115. ctx.JSON(http.StatusOK, rsp)
  116. }
  117. func (c *auth) Clear(ctx *gin.Context) {
  118. //todo clear redis
  119. ctx.JSON(http.StatusOK, util.SuccessResponse(util.Success, nil))
  120. }
  121. func (c *auth) Login(ctx *gin.Context) {
  122. passKey := ctx.Query("passKey")
  123. tenant, err := service.TenantService.GetTenantByPasskey(passKey)
  124. if err != nil {
  125. ctx.JSON(http.StatusOK, util.SuccessResponse(model.TenantNotFound, nil))
  126. return
  127. }
  128. rsp := model.RspLogin{
  129. ID: tenant.TenantId,
  130. Name: tenant.LoginDisplayName,
  131. BackgroundUrl: tenant.BackgroundUrl,
  132. SysLogoUrl: tenant.SysLogoUrl,
  133. }
  134. ctx.JSON(http.StatusOK, util.SuccessResponse(util.Success, rsp))
  135. }
  136. //checkLock 校验用户登录失败次数
  137. func checkLock() {
  138. }
  139. func getRefreshToken(info model.UserInfo) string {
  140. claims := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{
  141. model.Iss: model.Issuer,
  142. model.Aud: model.Audience,
  143. model.ClientId: model.Saber,
  144. model.TokenType: model.RefreshToken,
  145. model.UserId: info.ID,
  146. model.Exp: time.Now().Add(7 * 24 * time.Hour).Unix(),
  147. model.Nbf: time.Now().Unix(),
  148. })
  149. token, _ := claims.SignedString([]byte(config.Instance().Server.TokenSign))
  150. return token
  151. }
  152. func parseRefreshToken(refreshToken string) *jwt.MapClaims {
  153. token, err := jwt.ParseWithClaims(refreshToken, &jwt.MapClaims{}, middleware.EmptyKeyFunc)
  154. if err != nil {
  155. return nil
  156. }
  157. return token.Claims.(*jwt.MapClaims)
  158. }
  159. func captchaGrant(token model.Token, ctx *gin.Context) (*model.UserInfo, *util.Errors) {
  160. info := &model.UserInfo{}
  161. key := ctx.GetHeader(model.CaptchaHeaderKey)
  162. code := ctx.GetHeader(model.CaptchaHeaderCode)
  163. // 获取验证码
  164. result, err := util.Redis.Get(getCaptchaKey(key)).Result()
  165. if err != nil {
  166. return nil, util.NormalResponse(http.StatusBadRequest, model.CaptchaNotCorrect, nil)
  167. }
  168. redisCode := result
  169. // 判断验证码
  170. if config.Instance().Server.CodeEnabled && (key == "" || code == "" || !strings.EqualFold(redisCode, code)) {
  171. return nil, util.NormalResponse(http.StatusBadRequest, model.CaptchaNotCorrect, nil)
  172. }
  173. if token.UserName != "" && token.Password != "" {
  174. // 获取租户信息
  175. tenant, _ := service.TenantService.GetOne(token.TenantId)
  176. if tenant == nil {
  177. return nil, util.NormalResponse(http.StatusOK, model.UserHasNoTenant, nil)
  178. }
  179. if judgeTenant(tenant) {
  180. return nil, util.NormalResponse(http.StatusOK, model.UserHasNoTenantPermission, nil)
  181. }
  182. // 获取用户类型
  183. // 根据不同用户类型调用对应的接口返回数据,用户可自行拓展
  184. info.User = service.UserService.GetOne(token.TenantId, token.UserName, token.Password)
  185. info.TenantId = token.TenantId
  186. info.Roles = []string{"admin"}
  187. }
  188. //todo 操作记录
  189. return info, nil
  190. }
  191. func refreshGrant(token model.Token) (*model.UserInfo, *util.Errors) {
  192. info := &model.UserInfo{}
  193. jwtToken := parseRefreshToken(token.RefreshToken)
  194. if jwtToken == nil || len(*jwtToken) != 7 {
  195. return nil, util.NormalResponse(http.StatusOK, model.UserHasNoTenantPermission, nil)
  196. }
  197. // 获取租户信息
  198. tenant, _ := service.TenantService.GetOne(token.TenantId)
  199. if tenant == nil {
  200. return nil, util.NormalResponse(http.StatusOK, model.UserHasNoTenant, nil)
  201. }
  202. if judgeTenant(tenant) {
  203. return nil, util.NormalResponse(http.StatusOK, model.UserHasNoTenantPermission, nil)
  204. }
  205. info.User = service.UserService.GetOneByTenantId(token.TenantId)
  206. info.Roles = []string{"admin"}
  207. //todo 操作记录
  208. return info, nil
  209. }
  210. func judgeTenant(tenant *dao.Tenant) bool {
  211. if tenant.TenantId == model.AdminTenantId {
  212. return false
  213. }
  214. if tenant.ExpireTime.IsZero() || !tenant.ExpireTime.Before(time.Now()) {
  215. return false
  216. }
  217. return true
  218. }
  219. func getAccessTokenKey(tenantId string, uId int64, random string) string {
  220. return fmt.Sprintf("access_token_%s_%d_%s", tenantId, uId, random)
  221. }
  222. func getCaptchaKey(uId string) string {
  223. return fmt.Sprintf("auth:captcha:%s", uId)
  224. }