gin-图形验证码

文档地址:https://mojotv.cn/go/refactor-base64-captcha

1. 在api接口文件中配置生成验证码的代码

在user-web/api下面创建chaptcha.go文件

package api

//导入
import (
	"github.com/gin-gonic/gin"
	"github.com/mojocn/base64Captcha"
	"go.uber.org/zap"
	"net/http"
)

//文档:https://mojotv.cn/go/refactor-base64-captcha

// 做验证码保存
var store = base64Captcha.DefaultMemStore

func GetCaptcha(ctx *gin.Context) {
	driver := base64Captcha.NewDriverDigit(240, 80, 5, 0.7, 80)
	cp := base64Captcha.NewCaptcha(driver, store)
	id, b64s, err := cp.Generate()
	if err != nil {
		zap.S().Errorf("生成验证码错误,: ", err.Error())
		ctx.JSON(http.StatusInternalServerError, gin.H{
			"msg": "生成验证码错误",
		})
		return
	}
	ctx.JSON(http.StatusOK, gin.H{
		"captchaId":id,
		"picPath": b64s,
	})
}

  

2. 添加路由

在user-web/route下面创建base.go文件

package router

import (
	"github.com/gin-gonic/gin"
	"mxshop-api/user-web/api"
)

func InitBaseRoute(Route *gin.RouterGroup) {
	BaseRoute := Route.Group("base")
	{
		BaseRoute.GET("captcha", api.GetCaptcha)
	}
}

  

3. 初始化路由

package initialize

import (
	"github.com/gin-gonic/gin"
	"mxshop-api/user-web/middlewares"
	"mxshop-api/user-web/router"
)

func Routers() *gin.Engine {
	Router := gin.Default()
	//配置跨域
	Router.Use(middlewares.Cors())
	ApiGroup := Router.Group("v1")
	router.InitUserRoute(ApiGroup)
	router.InitBaseRoute(ApiGroup)
	return Router
}

  

4.  请求接口

http://127.0.0.1:8021/v1/base/captcha

{"captchaId":"Y2C3XDKk92GQExz44SqM","picPath":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFAAAADwCAMAAACg0xNxAAAA81BMVEUAAAB+MGtwIl10JmFyJF9qHFdnGVS/cayIOnWCNG+NP3qsXpldD0qAMm2cTolSBD99L2qxY56gUo2MPnlpG1aiVI+dT4qzZaB6LGfFd7KoWpVaDEejVZB3KWSURoHNf7rKfLekVpG6bKePQXyxY55uIFtvIVxzJWCHOXRPATx8LmmfUYxkFlF7LWiSRH+KPHeIOnVnGVRhE06KPHfEdrF6LGeSRH/OgLtqHFdRAz5xI16HOXRVB0LCdK93KWSyZJ+bTYhjFVBlF1JcDkm1Z6KrXZhwIl2CNG9XCURyJF+8bqmRQ358Lml7LWiwYp1iFE+dT4rWbgCSAAAAAXRSTlMAQObYZgAAA6VJREFUeJzs21lL60AUB/CJIFwXWn0Q8cEd+lBQXFCjVUEpoqDf/+tcbNLMdpI5M+cft87/wdt2Or+epGluMpmo35mT4DuuuxpfPe8kJF5fd4ivr74Y8GIrROZBDbHew3AIFsEV9pOigGJ1cGDNVs8w6NQoFFHrdDqdOYVeA+IKtYEo1OrerNNEs+o361sQLc2qiAMr0qqoesJc/jPKNLad+YuNHADPzgixfqDUQDOqebFesyu8CnUBRVEMBoO5Ym3yn39XVtpE1zMfDMwVqFtn//A8B1TuplPYbe2Mt8DKWHLdZqyPUF3Or9f6Xq338UBjieZ/vAIdMQC6sn7qNfMqtHv5BclAs3/bK8mg27G1xL14u7PEvb14cV6h9f9OeoXu7ssBL+M9VZj7X9e7TBEdubPCHarjVZfY/Zk7O4R4ddUqhhOs8DTdJnN6ChfB3u/MLdq7hYtgz0747CvSC54fRotgb3GyhvbW4CLjPfsxIOOgc39/Jh75LbuExzksrrwjT9zdpcSwV4dXYU4OJ5JjNtITHQWSItjLyfm2HKK9Q0dcFouOtywWlT0WvXwj96zR8psbgGg9k3t95jm6hzv653jPsaI3PumKkV6owkXLP7T3Dy6CvRwnq2hvFS6CPXHG1eU1nDceq+lUJA7VgSVeXMgqHA4PDizxQqIpv8I/mffm0TbGe5+L29sgsXmE8XKI3KG9u0Y8BomNdwwSm1AecrKEgUKYEkyWZWk9ly97KevOSj/fEF7so0x4etrcv2zJ0/df9JIb+69E1BMlnoLNYCJdumEkMn10NKJE/hCmnhxUXbJXakR8Ttwga6Fda+bRJKnC9kwmE4BiiWDva9J5YpRw2bLz1C3pwiq6QlHIORNNzjva6B8vOatDe+ftIv3jxVeYw0yPR+y8vATFSO8lKEYG7fHyhvbe4CLYy1nIbKG9rWjxKSBGe08BMTpy72/sTzbkH2PdtrSxIRadG6vQFeb87EAn5t2Cp/rN5sSiK8xBBj3GWZYleIJ5yZoCHzeixPDgY1S/YPz0iyK4/eIzS54nuaFDqaUlX+T0a9+IPI+VfKeHTtoa7PD871jVEwpSRdIbM0X2sBHXaxnYSk8vA1ubaG8TLoK9v5AfcIocEsHeT0toBk/snBJrjtE94UXPejG9e0qM9KwQXs5i5gPtfcDFtoZvvCuPeTjF96rDKeCFxMqzLnU+Srx6grrlPQpEcgo9osJFyDraW4eL+uH/AAAA///Hyj6PdBcIyQAAAABJRU5ErkJggg=="}

 

5. 验证

在密码验证之前先对验证码进行验证

在api/user.go中PassWordLogin配置

	if !store.Verify(passWordLoginForm.CaptchaId, passWordLoginForm.Captcha, true) {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"captcha": "验证码错误",
		})
		return
	}

  

 

全部内容如下

unc PassWordLogin(ctx *gin.Context) {
	//密码登录的接口
	//1.表单验证, 在forms中定义
	//ctx.JSON(http.StatusOK, "密码登录")
	passWordLoginForm := forms.PassWordLoginForm{}

	//固定格式
	if err := ctx.ShouldBind(&passWordLoginForm); err != nil {
		HandleValidatorError(ctx, err)
		return
	}

	if !store.Verify(passWordLoginForm.CaptchaId, passWordLoginForm.Captcha, true) {
		ctx.JSON(http.StatusBadRequest, gin.H{
			"captcha": "验证码错误",
		})
		return
	}

	//拨号连接用户RPC服务
	userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", global.ServerConfig.UserSrvInfo.Host, global.ServerConfig.UserSrvInfo.Port), grpc.WithTransportCredentials(insecure.NewCredentials()))
	if err != nil {
		zap.S().Errorw("[GetUserList]连接失败【用户服务失败】", "msg", err.Error())
	}
	//生成grpc的client并调用接口
	userSrvClient := proto.NewUserClient(userConn)

	//	登录的逻辑, 查询是否存在,密码是否相等
	if rsp, err := userSrvClient.GetUserByMobile(context.Background(), &proto.MobileRequests{
		Mobile: passWordLoginForm.Mobile,
	}); err != nil {
		if e, ok := status.FromError(err); ok {
			switch e.Code() {
			case codes.NotFound:
				ctx.JSON(http.StatusBadRequest, map[string]string{
					"mobile": "用户不存在",
				})
			default:
				ctx.JSON(http.StatusBadRequest, map[string]string{
					"mobile": "登录失败",
				})
			}
			return
		}
	} else {
		//	只是查询了用户而已,并没有检查密码
		if passRsp, pasErr := userSrvClient.CheckPassWord(context.Background(), &proto.PasswordCheckInfo{
			Password:          passWordLoginForm.PassWord,
			EncryptedPassword: rsp.PassWord,
		}); pasErr != nil {
			ctx.JSON(http.StatusInternalServerError, map[string]string{
				"password": "登录失败",
			})
		} else {
			if passRsp.Success {
				//生成token
				j := middlewares.NewJWT()
				claims := models.CustomClaims{
					ID:          uint(rsp.Id),
					NickName:    rsp.NickName,
					AuthorityId: uint(rsp.Role),
					StandardClaims: jwt.StandardClaims{
						NotBefore: time.Now().Unix(),               //签名的生效时间
						ExpiresAt: time.Now().Unix() + 60*60*24*30, //30day过期
						Issuer:    "wanghui",
					},
				}
				token, err := j.CreateToken(claims)
				if err != nil {
					ctx.JSON(http.StatusInternalServerError, map[string]string{
						"msg": "生成token失败",
					})
					return
				}

				ctx.JSON(http.StatusOK, gin.H{
					"id":         rsp.Id,
					"nick_name":  rsp.NickName,
					"token":      token,
					"expired_at": time.Now().Unix() + 60*60*24*30*1000,
				})
			} else {
				ctx.JSON(http.StatusBadRequest, map[string]string{
					"msg": "登录失败",
				})
			}

		}

	}
}

  修改PassWordLoginForm验证规则

package forms

type PassWordLoginForm struct {
	Mobile    string `form:"mobile"  json:"mobile" binding:"required,mobile"` //手机号码规则验证,自定义validator
	PassWord  string `form:"password"  json:"password" binding:"required,min=3,max=20"`
	Captcha   string `form:"captcha" json:"captcha" binding:"required,min=5,max=5"`
	CaptchaId string `form:"captcha_id" json:"captcha_id" binding:"required,min=5"`
}

  

 

posted @ 2022-11-05 13:43  wanghhhh  阅读(362)  评论(0)    收藏  举报