图形验证码
如何嵌入图形验证码工作:
这里选择使用captcha 开源库进行验证码设计:
选用下面的地址进行验证码开发工作
https://zh.mojotv.cn/go/refactor-base64-captcha
基础功能构建
在 api 目录下创建 captcha.go 用来编写验证码操作
package api
import (
"github.com/gin-gonic/gin"
"github.com/mojocn/base64Captcha"
"go.uber.org/zap"
"net/http"
)
// 使用内存方式存储验证码信息
var store = base64Captcha.DefaultMemStore
func GetCaptcha(ctx *gin.Context) {
// 配置验证码参数,数字、高:80、宽:240,长度:5、倾斜程度:0.7、背景圆圈数量:80
driver := base64Captcha.NewDriverDigit(80, 240, 5, 0.7, 80)
// 结合参数与生成方式,创建验证码生成器
cp := base64Captcha.NewCaptcha(driver, store)
id, b64s, _, err := cp.Generate()
if err != nil {
zap.S().Errorf("生成验证码错误:%s", err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{
"msg": "验证码生成错误",
})
}
// 若没有发生错误:将图片id 和 图片的 base64 编码作为参数传递
ctx.JSON(http.StatusOK, gin.H{
"captchaId": id,
"picPath": b64s,
})
}
功能嵌入路由
将验证码放入路由:
在 router 目录下创建文件:base.go:
package api
import (
"github.com/gin-gonic/gin"
"github.com/mojocn/base64Captcha"
"go.uber.org/zap"
"net/http"
)
// 使用内存方式存储验证码信息
var store = base64Captcha.DefaultMemStore
func GetCaptcha(ctx *gin.Context) {
// 配置验证码参数,数字、高:240、宽:80,长度:5、倾斜程度:0.7、背景圆圈数量:80
driver := base64Captcha.NewDriverDigit(80, 240, 5, 0.7, 80)
// 结合参数与生成方式,创建验证码生成器
cp := base64Captcha.NewCaptcha(driver, store)
id, b64s, _, err := cp.Generate()
if err != nil {
zap.S().Errorf("生成验证码错误:%s", err.Error())
ctx.JSON(http.StatusInternalServerError, gin.H{
"msg": "验证码生成错误",
})
}
// 若没有发生错误:将图片id 和 图片的 base64 编码作为参数传递
ctx.JSON(http.StatusOK, gin.H{
"captchaId": id,
"picPath": b64s,
})
}
将base 的router 配置到初始化的 Initialize 目录中的 router 初始化中:
func Routers() *gin.Engine {
Router := gin.Default()
// 配置跨域的拦截器
Router.Use(middlewares.Cors())
ApiGroup := Router.Group("/u/v1")
router2.InitUserRouter(ApiGroup)
router2.InitBaseRouter(ApiGroup)
return Router
}
我们可以在前端直接做一个展示:
<img src="data:image/png;base64,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" alt="">
将验证码验证逻辑添加到登录逻辑中:
修改 form/user.go 添加验证码逻辑
package forms
// 这里要注意 binding 内部的参数不可以加空格
// 请求中需要有 手机号、密码、验证码信息
type PassWordLoginForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"`
PassWord string `form:"password" json:"password" binding:"required,min=3,max=10"`
Captcha string `form:"captcha" json:"captcha" binding:"required,min=5,max=5"`
Captcha_id string `form:"captcha_id" json:"captcha_id" binding:"required"`
}
再对 api/user.go 中的登录方法进行改造:
// 绑定请求参数
passwordLoginForm := forms.PassWordLoginForm{}
if err := c.ShouldBind(&passwordLoginForm); err != nil {
HandleValidatorError(c, err)
}
// 下面是新增部分,再请求参数绑定后 进行验证码验证逻辑
// 直接使用 store 进行验证码验证,由于store 是在同一个 package 下的,所以该变量也可以直接使用
// 若验证不正确则报错
if !store.Verify(passwordLoginForm.CaptchaId, passwordLoginForm.Captcha, true) {
c.JSON(http.StatusBadRequest, gin.H{
"captcha": "验证码错误",
})
return
}
之后POST访问登录:
BODY:
{
"mobile": "13001350015",
"password": "admin123",
"captchaId": "y2uaAcBujzdUXz0DgX6b",
"captcha": "56570"
}
短信验证码
阿里云短信接口
稍后在 api 目录下进行开发,构建 api/sms.go 用来处理短信验证码的核心逻辑:
package api
import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
"github.com/gin-gonic/gin"
)
func SendSms(ctx *gin.Context) {
client, err := dysmsapi.NewClientWithAccessKey("cn-beijing", 你的acessKey, 你的acessSecret)
if err != nil {
panic(err)
}
request := requests.NewCommonRequest()
request.Method = "POST"
request.Scheme = "https"
request.Domain = "dysmsapi.aliyuncs.com"
request.Version = "2017-05-25" // 必须写这个日期
request.ApiName = "SendSms"
// 直接写,无需在阿里云上配置
request.QueryParams["RegionId"] = "cn-beijing"
request.QueryParams["PhoneNumbers"] = 发送的手机号
// 这里要写 签名的名字,注意是名字
request.QueryParams["SignName"] = 你的签名名称
// 这里要写模版的 id,注意是 id
request.QueryParams["TemplateCode"] = 你的模版id
// 参照你的模版发送请求,注意中间的验证码是可以自定义生成的
request.QueryParams["TemplateParam"] = "{\"code\":" + "77777" + "}"
response, err := client.ProcessCommonRequest(request)
fmt.Println(client.DoAction(request, response))
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("response is %#v\n", response)
}
添加随机生成验证码的逻辑:
api/sms.go:
package api
import (
"fmt"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
"github.com/gin-gonic/gin"
"math/rand"
"strings"
"time"
)
// 随机验证码的生成
func GenerateSmsCode(width int) string {
numeric := [10]byte{0,1,2,3,4,5,6,7,8,9}
r := len(numeric)
// 随机数种子
rand.Seed(time.Now().Unix())
var sb strings.Builder
for i := 0; i < width; i++ {
fmt.Fprintf(&sb, "%d", numeric[rand.Intn(r)])
}
return sb.String()
}
func SendSms(ctx *gin.Context) {
client, err := dysmsapi.NewClientWithAccessKey("cn-beijing", "LTAI5tHRZ7GqMXx271nxuSgd", "tJErGmml9ArkhJmMoo0QK1BaJnlCWM")
if err != nil {
panic(err)
}
request := requests.NewCommonRequest()
request.Method = "POST"
request.Scheme = "https"
request.Domain = "dysmsapi.aliyuncs.com"
request.Version = "2017-05-25"
request.ApiName = "SendSms"
// 直接写,无需在阿里云上配置
request.QueryParams["RegionId"] = "cn-beijing"
request.QueryParams["PhoneNumbers"] = "13001350015"
// 这里要写 签名的名字,注意是名字
request.QueryParams["SignName"] = "清河个人博客网站"
// 这里要写模版的 id,注意是 id
request.QueryParams["TemplateCode"] = "SMS_461975751"
// 参照你的模版发送请求,注意中间的验证码是可以自定义生成的
request.QueryParams["TemplateParam"] = "{\"code\":" + GenerateSmsCode(6) + "}"
response, err := client.ProcessCommonRequest(request)
fmt.Println(client.DoAction(request, response))
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("response is %#v\n", response)
// TODO 将验证码保存到 redis 以手机号为 key, 以验证码为 value
}
验证码redis存储
虚拟机拉取 redis:
docker run -d --name redis -p 6379:6379 \
-v /mydata/redis:/usr/local/etc/redis \
redis
redis 默认数据库有 16 个 (0 - 15)
默认连接会连接到第一个 0 的 redis 数据库
将短信中的信息修改为从配置文件中读取:
在 config/config,go 中进行添加需要的配置信息:
package config
type UserSrvConfig struct {
Host string `mapstructure:"host"`
Port int32 `mapstructure:"port"`
}
type ServerConfig struct {
Name string `mapstructure:"name"`
Port int32 `mapstructure:"port"`
UserSrvInfo UserSrvConfig `mapstructure:"user_srv"`
JWTInfo JWTConfig `mapstructure:"jwt"`
AliSmsInfo AliSmsConfig `mapstructure:"sms"`
RedisInfo RedisConfig `mapstructure:"redis"`
}
type JWTConfig struct {
SigningKey string `mapstructure:"key"`
}
// redis 配置
type RedisConfig struct {
Host string `mapstructure:"host"`
Port uint `mapstructure:"port"`
Expire int `mapstructure:"expire"`
}
// 阿里云信息配置
type AliSmsConfig struct {
ApiKey string `mapstructure:"key"`
ApiSecret string `mapstructure:"secret"`
}
配置文件的修改不再显示,这里显示修改之后的核心代码:
package api
import (
"context"
"fmt"
"math/rand"
"mxshop-api/user-web/forms"
"net/http"
"strings"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
"mxshop-api/user-web/global"
)
// 随机验证码的生成
func GenerateSmsCode(width int) string {
numeric := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
r := len(numeric)
// 随机数种子
rand.Seed(time.Now().Unix())
var sb strings.Builder
for i := 0; i < width; i++ {
fmt.Fprintf(&sb, "%d", numeric[rand.Intn(r)])
}
return sb.String()
}
func SendSms(ctx *gin.Context) {
// 表单验证 要求必须传入手机号和 验证码类型
sendSmsForm := forms.SendSmsForm{}
if err := ctx.ShouldBind(&sendSmsForm); err != nil {
HandleValidatorError(ctx, err)
return
}
client, err := dysmsapi.NewClientWithAccessKey("cn-beijing", global.ServerConfig.AliSmsInfo.ApiKey, global.ServerConfig.AliSmsInfo.ApiSecret)
smsCode := GenerateSmsCode(6)
if err != nil {
panic(err)
}
request := requests.NewCommonRequest()
request.Method = "POST"
request.Scheme = "https"
request.Domain = "dysmsapi.aliyuncs.com"
request.Version = "2017-05-25"
request.ApiName = "SendSms"
// 直接写,无需在阿里云上配置
request.QueryParams["RegionId"] = "cn-beijing"
request.QueryParams["PhoneNumbers"] = sendSmsForm.Mobile
// 这里要写 签名的名字,注意是名字
request.QueryParams["SignName"] = "清河个人博客网站"
// 这里要写模版的 id,注意是 id
request.QueryParams["TemplateCode"] = "SMS_461975751"
// 参照你的模版发送请求,注意中间的验证码是可以自定义生成的
request.QueryParams["TemplateParam"] = "{\"code\":" + smsCode + "}"
response, err := client.ProcessCommonRequest(request)
fmt.Println(client.DoAction(request, response))
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("response is %#v\n", response)
// 将验证码保存到 redis 以手机号为 key, 以验证码为 value
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.ServerConfig.RedisInfo.Host, global.ServerConfig.RedisInfo.Port),
})
rdb.Set(context.Background(), sendSmsForm.Mobile, smsCode, time.Duration(global.ServerConfig.RedisInfo.Expire)*time.Second)
ctx.JSON(http.StatusOK, gin.H{
"msg": "验证码发送成功",
})
}
将验证码存储进 redis
拉取 redis 的 go 语言库:go-redis:
package api
import (
"context"
"fmt"
"math/rand"
"strings"
"time"
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
"github.com/aliyun/alibaba-cloud-sdk-go/services/dysmsapi"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
"mxshop-api/user-web/global"
)
// 随机验证码的生成
func GenerateSmsCode(width int) string {
numeric := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
r := len(numeric)
// 随机数种子
rand.Seed(time.Now().Unix())
var sb strings.Builder
for i := 0; i < width; i++ {
fmt.Fprintf(&sb, "%d", numeric[rand.Intn(r)])
}
return sb.String()
}
func SendSms(ctx *gin.Context) {
client, err := dysmsapi.NewClientWithAccessKey("cn-beijing", global.ServerConfig.AliSmsInfo.ApiKey, global.ServerConfig.AliSmsInfo.ApiSecret)
mobile := "13001350015"
smsCode := GenerateSmsCode(6)
if err != nil {
panic(err)
}
request := requests.NewCommonRequest()
request.Method = "POST"
request.Scheme = "https"
request.Domain = "dysmsapi.aliyuncs.com"
request.Version = "2017-05-25"
request.ApiName = "SendSms"
// 直接写,无需在阿里云上配置
request.QueryParams["RegionId"] = "cn-beijing"
request.QueryParams["PhoneNumbers"] = mobile
// 这里要写 签名的名字,注意是名字
request.QueryParams["SignName"] = "清河个人博客网站"
// 这里要写模版的 id,注意是 id
request.QueryParams["TemplateCode"] = "SMS_461975751"
// 参照你的模版发送请求,注意中间的验证码是可以自定义生成的
request.QueryParams["TemplateParam"] = "{\"code\":" + smsCode + "}"
response, err := client.ProcessCommonRequest(request)
fmt.Println(client.DoAction(request, response))
if err != nil {
fmt.Println(err.Error())
}
fmt.Printf("response is %#v\n", response)
// 将验证码保存到 redis 以手机号为 key, 以验证码为 value
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.ServerConfig.RedisInfo.Host, global.ServerConfig.RedisInfo.Port),
})
rdb.Set(context.Background(), mobile, smsCode, 30*time.Second)
ctx.JSON(http.StatusOK, gin.H{
"msg": "验证码发送成功",
})
}
另外,该接口还涉及到 form 表单问题,要求手机号必须填写:
在 form 目录下新建一个 go 文件:form/sms.go
package forms
// 这里要注意 binding 内部的参数不可以加空格
// 请求中需要有 手机号、密码、验证码输入信息、验证码图片信息
type SendSmsForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"`
// 这里为了区分开登录和注册的逻辑,包括具体场景下会出现的 找回密码等逻辑,需要添加一个 Type 表单
Type uint `form:"type" json:"type" binding:"required,oneof=1 2"`
}
之后在 核心逻辑中添加表单验证的代码:
func SendSms(ctx *gin.Context) {
// 表单验证 要求必须传入手机号和 验证码类型
sendSmsForm := forms.SendSmsForm{}
if err := ctx.ShouldBind(&sendSmsForm); err != nil {
HandleValidatorError(ctx, err)
return
}
client, err := dysmsapi.NewClientWithAccessKey("cn-beijing", global.ServerConfig.AliSmsInfo.ApiKey, global.ServerConfig.AliSmsInfo.ApiSecret)
smsCode := GenerateSmsCode(6)
......
在router/base.go 中添加发送短信验证码的路由:
package router
import (
"github.com/gin-gonic/gin"
"mxshop-api/user-web/api"
)
func InitBaseRouter(Router *gin.RouterGroup) {
BaseRouter := Router.Group("base")
{
BaseRouter.GET("captcha", api.GetCaptcha)
// TODO
BaseRouter.POST("send_sms", api.SendSms)
}
}
之后,手机会收到验证码,验证码也会被存储在 redis 中
注册接口
创建核心逻辑的方法:
api/user.go
func Register(ctx *gin.Context) {
// 配置传入的表单
}
在 forms / user.go 中添加表单验证信息:
type RegisterForm struct {
Mobile string `form:"mobile" json:"mobile" binding:"required,mobile"`
Password string `form:"password" json:"password" binding:"required,min=3,max=10"`
Code string `form:"code" json:"code" binding:"required,min=6,max=6"`
}
之后继续编写注册的核心逻辑
api/user.go
func Register(ctx *gin.Context) {
registerForm := forms.RegisterForm{}
// 配置传入的表单,进行表单验证
if err := ctx.ShouldBind(®isterForm); err != nil {
HandleValidatorError(ctx, err)
return
}
// 进行短信验证码校验
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.ServerConfig.RedisInfo.Host, global.ServerConfig.RedisInfo.Port),
})
if value, err := rdb.Get(context.Background(), registerForm.Mobile).Result(); err == redis.Nil {
zap.S().Debug("key 不存在")
ctx.JSON(http.StatusBadRequest, gin.H{
"code": "验证码过期或未发送验证码",
})
return
} else if value != registerForm.Code {
ctx.JSON(http.StatusBadRequest, gin.H{
"code": "验证码错误",
})
return
}
// 用户拨号连接 grpc 服务
userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", global.ServerConfig.UserSrvInfo.Host, global.ServerConfig.UserSrvInfo.Port), grpc.WithInsecure())
if err != nil {
zap.S().Errorw("[Register] 连接用户服务器失败", "msg", err.Error())
}
// 生成用户模块的 grpc 接口并调用
userSrvClient := proto.NewUserClient(userConn)
user, err := userSrvClient.CreateUser(context.Background(), &proto.CreateUserInfo{
Nickname: registerForm.Mobile,
Password: registerForm.Password,
Mobile: registerForm.Mobile,
})
if err != nil {
zap.S().Errorf("[Register] 创建用户 失败")
HandleGrpcErrorToHttp(err, ctx)
return
}
// 注册成功,自动登录,生成登录的ToKEN
// 登录成功,生成TOKEN
j := middlewares.NewJWT() // 获得签名
// 构建传递的信息以及签名信息
claims := models.CustomClaims{
ID: uint(user.Id),
NickName: user.NickName,
AuthorityID: uint(user.Role),
StandardClaims: jwt.StandardClaims{ // 签名相关信息
NotBefore: time.Now().Unix(), // 签名生效时间:现在
ExpiresAt: time.Now().Unix() + 60*60*24*30, // 签名过期时间,从现在开始一个月
Issuer: "BaiLu", // 签名 对象 (公司)
},
}
// 真正创建 TOKEN:
token, err := j.CreateToken(claims)
if err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{
"msg": "TOKEN生成失败",
})
return
}
ctx.JSON(http.StatusOK, gin.H{
"id": user.Id,
"nick_name": user.NickName,
"token": token,
"expired_at": (time.Now().Unix() + 60*60*24*30) * 1000,
})
}
将 Register 添加到 Router 中
router/user.go
func InitUserRouter(Router *gin.RouterGroup) {
// 这样就需要 /user/list 才可以进行访问了
UserRouter := Router.Group("user")
{
// 在这里添加拦截器的作用响应位置
UserRouter.GET("list", middlewares.JWTAuth(), middlewares.IsAdminAuth(), api.GetUserList)
//UserRouter.GET("list", api.GetUserList)
UserRouter.POST("pwd_login", api.PassWordLogin)
UserRouter.POST("register", api.Register)
}
}