package controller import ( "fmt" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt" "github.com/mojocn/base64Captcha" "github.com/satori/go.uuid" "iot_manager_service/app/system/service" "strconv" "time" "iot_manager_service/app/system/model" "iot_manager_service/config" "iot_manager_service/util" "net/http" "strings" ) var Auth = new(auth) type auth struct{} var driver = &base64Captcha.DriverString{ Height: 48, Width: 130, NoiseCount: 100, ShowLineOptions: 2, Length: 5, BgColor: nil, } func (c *auth) Token(ctx *gin.Context) { tenantId := ctx.Query("tenantId") userName := ctx.Query("username") password := ctx.Query("password") grantType := ctx.Query("grant_type") refreshToken := ctx.Query("refresh_token") // 校验连续登录失败次数 checkLock() userType := ctx.GetHeader(model.UserTypeHeaderKey) token := model.Token{ TenantId: tenantId, UserName: userName, Password: password, GrantType: grantType, RefreshToken: refreshToken, UserType: userType, } userInfo, err := grant(token, ctx) if err != nil { ctx.JSON(http.StatusOK, err) return } if userInfo == nil || userInfo.ID == 0 { ctx.JSON(http.StatusOK, util.NormalResponse(http.StatusBadRequest, model.UserNotFound, nil)) return } if len(userInfo.Roles) == 0 { ctx.JSON(http.StatusOK, util.NormalResponse(http.StatusBadRequest, model.UserHasNoRole, nil)) return } // access token过期时间2小时 random := util.RandomString(8) jwtToken, e := getAccessToken(*userInfo, random) if e != nil { ctx.JSON(http.StatusOK, util.NormalResponse(http.StatusBadRequest, e.Error(), nil)) return } // redis记录缓存2小时 util.Redis.Set(getAccessTokenKey(userInfo.TenantId, userInfo.ID, random), jwtToken, 2*time.Hour) ctx.JSON(http.StatusOK, model.RspToken{ TenantId: userInfo.TenantId, UserId: strconv.FormatInt(userInfo.ID, 10), DeptId: userInfo.DeptId, PostId: userInfo.PostId, RoleId: userInfo.RoleId, OauthId: userInfo.OauthId, Account: userInfo.Account, UserName: userInfo.Name, NickName: userInfo.RealName, RoleName: userInfo.Roles[0], Avatar: userInfo.Avatar, AccessToken: jwtToken, RefreshToken: getRefreshToken(*userInfo), TokenType: model.BEARER, ExpiresIn: 7200, License: "", }) } func (c *auth) Logout(ctx *gin.Context) { emptyKeyFunc := func(t *jwt.Token) (interface{}, error) { return []byte(config.Instance().Server.TokenSign), nil } authorization := ctx.GetHeader("Authorization") token, err := jwt.ParseWithClaims(authorization, &model.JwtToken{}, emptyKeyFunc) if err != nil { ctx.JSON(http.StatusUnauthorized, util.NormalResponse(http.StatusUnauthorized, err.Error(), nil)) return } jwtToken := token.Claims.(*model.JwtToken) err = util.Redis.Del(getAccessTokenKey(jwtToken.TenantId, jwtToken.UserId, jwtToken.Random)).Err() //todo 操作记录 ctx.JSON(http.StatusOK, util.SuccessResponse("", nil)) } func (c *auth) Captcha(ctx *gin.Context) { id := uuid.NewV1().String() code := util.RandomString2(5) gotItem, _ := driver.DrawCaptcha(code) image := gotItem.EncodeB64string() rsp := model.RspCaptcha{ Key: id, Image: image, } util.Redis.Set(getCaptchaKey(id), code, 5*time.Minute) ctx.JSON(http.StatusOK, rsp) } func (c *auth) Clear(ctx *gin.Context) { //todo clear redis ctx.JSON(http.StatusOK, util.SuccessResponse(util.Success, nil)) } func (c *auth) Login(ctx *gin.Context) { passKey := ctx.Query("passKey") tenant, err := service.TenantService.Get(passKey) if err != nil { ctx.JSON(http.StatusOK, util.SuccessResponse(model.TenantNotFound, nil)) return } rsp := model.RspLogin{ ID: tenant.TenantId, } ctx.JSON(http.StatusOK, util.SuccessResponse(util.Success, rsp)) } //checkLock 校验用户登录失败次数 func checkLock() { } func getAccessToken(info model.UserInfo, random string) (string, error) { jwtToken := model.JwtToken{StandardClaims: jwt.StandardClaims{ Audience: "audience", ExpiresAt: time.Now().Add(2 * time.Hour).Unix(), Issuer: "issuser", NotBefore: time.Now().Unix(), }, UserId: info.ID, TenantId: info.TenantId, TokenType: "access_token", ClientId: "saber", RoleId: info.RoleId, RoleName: info.Roles[0], DeptId: info.DeptId, PostId: info.PostId, OauthId: info.OauthId, Account: info.Account, UserName: info.Account, NickName: info.RealName, Random: random, } claims := jwt.NewWithClaims(jwt.SigningMethodHS512, jwtToken) return claims.SignedString([]byte(config.Instance().Server.TokenSign)) } func getRefreshToken(info model.UserInfo) string { claims := jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{ model.Iss: "issuser", model.Aud: "audience", model.ClientId: "saber", model.TokenType: "refresh_token", model.UserId: info.ID, model.Exp: time.Now().Add(7 * 24 * time.Hour).Unix(), model.Nbf: time.Now().Unix(), }) token, _ := claims.SignedString([]byte(config.Instance().Server.TokenSign)) return token } func grant(token model.Token, ctx *gin.Context) (*model.UserInfo, *util.Errors) { info := &model.UserInfo{} key := ctx.GetHeader(model.CaptchaHeaderKey) code := ctx.GetHeader(model.CaptchaHeaderCode) // 获取验证码 result, err := util.Redis.Get(getCaptchaKey(key)).Result() if err != nil { return nil, util.NormalResponse(http.StatusBadRequest, model.CaptchaNotCorrect, nil) } redisCode := result // 判断验证码 if config.Instance().Server.CodeEnabled && (key == "" || code == "" || !strings.EqualFold(redisCode, code)) { return nil, util.NormalResponse(http.StatusBadRequest, model.CaptchaNotCorrect, nil) } if token.UserName != "" && token.Password != "" { // 获取租户信息 //Tenant tenant = tenantService.getByTenantId(tenantId); //if (TokenUtil.judgeTenant(tenant)) { // throw new ServiceException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION); //} // 获取用户类型 // 根据不同用户类型调用对应的接口返回数据,用户可自行拓展 // info.Auth = userService.GetUser(auth.tenantId, auth.UserName, auth.password) } //测试代码start info.TenantId = "000000" info.ID = 11112222 info.Roles = []string{"admin"} // 测试代码end //todo 操作记录 return info, nil } func getAccessTokenKey(tenantId string, uId int64, random string) string { return fmt.Sprintf("access_token_%s_%d_%s", tenantId, uId, random) } func getCaptchaKey(uId string) string { return fmt.Sprintf("auth:captcha:%s", uId) }