点瑞网络网站建设,网站做业务赚钱,seo搜索引擎优化就业前景,阿克顿巴网站建设的目的本次内容需要 gin框架基础知识, golang微服务基础知识才能更好理解 一.Captcha验证码功能引入 在前面,讲解了微服务的架构等,这里,来讲解前面商城项目的 Captcha验证码 微服务 ,captcha验证码功能在前台,后端 都要用到 ,可以把它 抽离出来 ,做成微服务功能 编辑 这个验证码功能…本次内容需要 gin框架基础知识, golang微服务基础知识才能更好理解 一.Captcha验证码功能引入
在前面,讲解了微服务的架构等,这里,来讲解前面商城项目的 Captcha验证码 微服务 ,captcha验证码功能在前台,后端 都要用到 ,可以把它 抽离出来 ,做成微服务功能 编辑
这个验证码功能封装代码captcha.go如下: package models//验证码属性: https://captcha.mojotv.cn/
import (github.com/mojocn/base64Captchaimage/color
)//创建store,保存验证码的位置,默认为mem(内存中)单机部署,如果要布置多台服务器,则可以设置保存在redis中
//var store base64Captcha.DefaultMemStore//配置RedisStore, 保存验证码的位置为redis, RedisStore实现base64Captcha.Store接口
var store base64Captcha.Store RedisStore{}//获取验证码
func MakeCaptcha(height int, width int, length int) (string, string, error) {//定义一个drivervar driver base64Captcha.Driver//创建一个字符串类型的验证码驱动DriverString, DriverChinese :中文驱动driverString : base64Captcha.DriverString{Height: height, //高度Width: width, //宽度NoiseCount: 0, //干扰数ShowLineOptions: 2 | 4, //展示个数Length: length, //长度Source: 1234567890qwertyuioplkjhgfdsazxcvbnm, //验证码随机字符串来源BgColor: color.RGBA{ // 背景颜色R: 3,G: 102,B: 214,A: 125,},Fonts: []string{wqy-microhei.ttc}, // 字体}driver driverString.ConvertFonts()//生成验证码c : base64Captcha.NewCaptcha(driver, store)id, b64s, err : c.Generate()return id, b64s, err
}//校验验证码
func VerifyCaptcha(id string, VerifyValue string) bool {// 参数说明: id 验证码id, verifyValue 验证码的值, true: 验证成功后是否删除原来的验证码if store.Verify(id, VerifyValue, true) {return true} else {return false}
} 把这个验证码做成微服务的话,就需要实现上面的两个方法: 获取验证码(MakeCaptcha), 校验验证码(VerifyCaptcha) 二.创建captcha验证码微服务服务端 创建两个文件夹,client(客户端),server(服务端) 生成服务端captcha微服务代码
在server目录下运行: go-micro new service captcha,生成captcha服务端代码 运行命令后,生成的服务端目录如下: 编写proto/captcha.proto文件
在这个文件中编写 获取验证码,验验证码相关代码 syntax proto3;package captcha;option go_package ./proto/captcha;service Captcha {//获取验证码: MakeCaptchaRequest请求, MakeCaptchaRequest返回rpc MakeCaptcha(MakeCaptchaRequest) returns (MakeCaptchaResponse) {}//校验验证码: VerifyCaptchaRequest请求, VerifyCaptchaResponse返回rpc VerifyCaptcha(VerifyCaptchaRequest) returns (VerifyCaptchaResponse) {}
}//以下具体参数类型参考captcha.go中对应的方法//获取验证码请求参数
message MakeCaptchaRequest {//验证码高度int32 height 1;//验证码宽度int32 width 2;//验证码长度int32 length 3;
}//获取验证码返回数据
message MakeCaptchaResponse {//验证码idstring id 1;//验证码base64编码string b64s 2;
}//校验验证码请求参数
message VerifyCaptchaRequest {//验证码idstring id 1;//输入的验证码string verifyValue 2;
}//校验验证码返回数据
message VerifyCaptchaResponse {//校验的结果bool verifyResult 1;
} 生成proto相关文件
参考 [golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例,windows下运行 Makefile里面的proto下的代码 :protoc --proto_path. --micro_out. --go_out:. proto/captcha.proto, 当然,如果是初次使用go-micro,则还需运行init下面的代码(go xxx),引入相关包 初始化项目
在captcha目录下运行命令: go mod init captcha,初始化项目 删除go.mod后再次执行 go mod init captcha命令: 运行命令 :go mod tidy,加载项目需要的包: 上面表示:下载 go-micro.dev/v4这个包失败了,这时则需运行命令 go get go-micro.dev/v4, 具体参考 : [golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例 在这里可能会出现 import中始终报红 的情况,解决见 : golang开启mod后import报红解决方案 启动consul服务发现
在cmd中运行命令: consul agent -dev,具体参考: [golang 微服务] 5. 微服务服务发现介绍,安装以及consul的使用,Consul集群 main.go中实例化consul
具体参考: [golang 微服务] 7. go-micro框架介绍,go-micro脚手架,go-micro结合consul搭建微服务案例,代码如下: package mainimport (captcha/handlerpb captcha/proto/captchago-micro.dev/v4go-micro.dev/v4/loggergithub.com/go-micro/plugins/v4/registry/consul
)var (service captchaversion latest
)func main() {//集成consulconsulReg : consul.NewRegistry()// Create servicesrv : micro.NewService(micro.Address(127.0.0.1:8081), //指定微服务的ip: 选择注册服务器地址,也可以不配置,默认为本机,也可以选择consul集群中的clientmicro.Name(service),micro.Version(version),//注册consulmicro.Registry(consulReg),)srv.Init(micro.Name(service),micro.Version(version),)// Register handlerif err : pb.RegisterCaptchaHandler(srv.Server(), new(handler.Captcha)); err ! nil {logger.Fatal(err)}// Run serviceif err : srv.Run(); err ! nil {logger.Fatal(err)}
} handler/captcha.go封装实现proto/captcha.proto里面的rpc方法
参考 proto/captcha.proto里面的 service Captcha 方法实现,也可以参考生成的 .pb.micro.go里面生成的方法进行实现 (1).pb.micro.go参考代码: // Client API for Captcha service
type CaptchaService interface {// 获取验证码: MakeCaptchaRequest请求, MakeCaptchaRequest返回MakeCaptcha(ctx context.Context, in *MakeCaptchaRequest, opts ...client.CallOption) (*MakeCaptchaResponse, error)// 校验验证码: VerifyCaptchaRequest请求, VerifyCaptchaResponse返回VerifyCaptcha(ctx context.Context, in *VerifyCaptchaRequest, opts ...client.CallOption) (*VerifyCaptchaResponse, error)
}
(2).handler/captcha.go代码:
把 一.Captcha验证码功能引入中captcha.go的代码复制到 handler/captcha.go中, 然后修修改改就可以了 1)首先,import github.com/mojocn/base64Captcha
把 github.com/mojocn/base64Captcha放入import中,然后通过 go mod tidy或者 go get github.com/mojocn/base64Captcha 引入 2).配置RedisStore
把 var store base64Captcha.Store RedisStore{}复制进去 //创建store,保存验证码的位置,默认为mem(内存中)单机部署,如果要布置多台服务器,则可以设置保存在redis中
//var store base64Captcha.DefaultMemStore//配置RedisStore, 保存验证码的位置为redis, RedisStore实现base64Captcha.Store接口
var store base64Captcha.Store RedisStore{}
这里使用的是 redis的存储方式,故需要 初始化redis,以及实现 设置 captcha 的方法的代码,故需要在captcha下创建 models/redisCore.go, models/redisStore.go文件,具体参考: [golang gin框架] 12.Gin 商城项目-base64Captcha生成图形验证码以及分布式架构中配置Captcha 初始化redis的代码
redisCore.go代码如下: package models//redis官网: github.com/go-redis
//下载go-redis: go get github.com/redis/go-redis/v9
//连接redis数据库核心代码import (contextfmtgithub.com/redis/go-redis/v9gopkg.in/ini.v1os
)//全局使用,就需要把定义成公有的
var ctxRedis context.Background()var (RedisDb *redis.Client
)//是否开启redis
var redisEnable bool//自动初始化数据库
func init() {//加载配置文件config, iniErr : ini.Load(./conf/app.ini)if iniErr ! nil {fmt.Printf(Fail to read file: %v, iniErr)os.Exit(1)}//获取redis配置ip : config.Section(redis).Key(ip).String()port : config.Section(redis).Key(port).String()redisEnable, _ config.Section(redis).Key(redisEnable).Bool()//判断是否开启redisif redisEnable {RedisDb redis.NewClient(redis.Options{Addr: ip : port,Password: , // no password setDB: 0, // use default DB})//连接redis_, err : RedisDb.Ping(ctxRedis).Result()//判断连接是否成功if err ! nil {println(err)}}
}
设置 captcha 的方法的代码 redisStore.go代码如下: package models/**
使用redis需实现Store中的三个方法
type Store interface {// Set sets the digits for the captcha id.Set(id string, value string)// Get returns stored digits for the captcha id. Clear indicates// whether the captcha must be deleted from the store.Get(id string, clear bool) string//Verify captchas answer directlyVerify(id, answer string, clear bool) bool
}*/import (contextfmttime
)var ctx context.Background()const CAPTCHA captcha:type RedisStore struct {
}//实现设置 captcha 的方法
func (r RedisStore) Set(id string, value string) error {key : CAPTCHA iderr : RedisDb.Set(ctx, key, value, time.Minute*2).Err()return err
}//实现获取 captcha 的方法
func (r RedisStore) Get(id string, clear bool) string {key : CAPTCHA id//获取 captchaval, err : RedisDb.Get(ctx, key).Result()if err ! nil {fmt.Println(err)return }//如果clear true, 则删除if clear {err : RedisDb.Del(ctx, key).Err()if err ! nil {fmt.Println(err)return }}return val
}//实现验证 captcha 的方法
func (r RedisStore) Verify(id, answer string, clear bool) bool {v : RedisStore{}.Get(id, clear)return v answer
}
这里使用了ini.Load加载
参考: [golang gin框架] 9.Gin GORM 中使用事务以及go-ini加载.ini配置文件 3).实现获取验证码方法的业务逻辑代码
把 一.Captcha验证码功能引入中captcha.go 获取验证码方法代码复制到handler/captcha.go的 MakeCaptcha,然后修修改改就可以了,代码如下 //获取验证码的方法
func (e *Captcha) MakeCaptcha(ctx context.Context, req *pb.MakeCaptchaRequest, rsp *pb.MakeCaptchaResponse) error {//实现业务逻辑代码//定义一个drivervar driver base64Captcha.Driver//创建一个字符串类型的验证码驱动DriverString, DriverChinese :中文驱动driverString : base64Captcha.DriverString{Height: int(req.Height), //高度Width: int(req.Width), //宽度NoiseCount: 0, //干扰数ShowLineOptions: 2 | 4, //展示个数Length: int(req.Length), //长度Source: 1234567890qwertyuioplkjhgfdsazxcvbnm, //验证码随机字符串来源BgColor: color.RGBA{ // 背景颜色R: 3,G: 102,B: 214,A: 125,},Fonts: []string{wqy-microhei.ttc}, // 字体}driver driverString.ConvertFonts()//生成验证码c : base64Captcha.NewCaptcha(driver, store)id, b64s, err : c.Generate()//把生成的验证码id,base64编码赋值给返回的rsp参数rsp.Id idrsp.B64S b64sreturn err
}
4).实现校验验证码方法的业务逻辑代码
把 一.Captcha验证码功能引入中captcha.go 校验验证码的方法代码复制到handler/captcha.go的 MakeCaptcha,然后修修改改就可以了,代码如下: //校验验证码的方法
func (e *Captcha) VerifyCaptcha(ctx context.Context, req *pb.VerifyCaptchaRequest, rsp *pb.VerifyCaptchaResponse) error {// 参数说明: id 验证码id, verifyValue 验证码的值, true: 验证成功后是否删除原来的验证码if store.Verify(req.Id, req.VerifyValue, true) {rsp.VerifyResult true //校验成功} else {rsp.VerifyResult false //校验失败}return nil
}
4).完整代码如下 package handlerimport (captcha/modelspb captcha/proto/captchacontextgithub.com/mojocn/base64Captchaimage/color
)//创建store,保存验证码的位置,默认为mem(内存中)单机部署,如果要布置多台服务器,则可以设置保存在redis中
//var store base64Captcha.DefaultMemStore//配置RedisStore, 保存验证码的位置为redis, RedisStore实现base64Captcha.Store接口
var store base64Captcha.Store models.RedisStore{}type Captcha struct{}//获取验证码的方法
func (e *Captcha) MakeCaptcha(ctx context.Context, req *pb.MakeCaptchaRequest, rsp *pb.MakeCaptchaResponse) error {//实现业务逻辑代码//定义一个drivervar driver base64Captcha.Driver//创建一个字符串类型的验证码驱动DriverString, DriverChinese :中文驱动driverString : base64Captcha.DriverString{Height: int(req.Height), //高度Width: int(req.Width), //宽度NoiseCount: 0, //干扰数ShowLineOptions: 2 | 4, //展示个数Length: int(req.Length), //长度Source: 1234567890qwertyuioplkjhgfdsazxcvbnm, //验证码随机字符串来源BgColor: color.RGBA{ // 背景颜色R: 3,G: 102,B: 214,A: 125,},Fonts: []string{wqy-microhei.ttc}, // 字体}driver driverString.ConvertFonts()//生成验证码c : base64Captcha.NewCaptcha(driver, store)id, b64s, err : c.Generate()//把生成的验证码id,base64编码赋值给返回的rsp参数rsp.Id idrsp.B64S b64sreturn err
}//校验验证码的方法
func (e *Captcha) VerifyCaptcha(ctx context.Context, req *pb.VerifyCaptchaRequest, rsp *pb.VerifyCaptchaResponse) error {// 参数说明: id 验证码id, verifyValue 验证码的值, true: 验证成功后是否删除原来的验证码if store.Verify(req.Id, req.VerifyValue, true) {rsp.VerifyResult true //校验成功} else {rsp.VerifyResult false //校验失败}return nil
} 注册验证码微服务服务端到服务发现(consul)
captcha目录下运行go run main.go,然后在consul UI 查看,是否注册成功 注册成功了 三.创建captcha验证码微服务客户端 在前面商城项目单体架构中生成客户端代码
前面单体架构商城中调用captcha验证码接口代码是通过接口 http://127.0.0.1:8080/admin/captcha这个访问的,具体代码如下: adminRouters.go //验证码
adminRouters.GET(/captcha, admin.LoginController{}.Captcha)
LoginController.go //获取验证码,验证验证码func(con LoginController) Captcha(c *gin.Context) {id, b64s, err : models.MakeCaptcha(50, 100 ,1)if err ! nil {fmt.Println(err)}c.JSON(http.StatusOK, gin.H{captchaId: id,captchaImage: b64s,})
}
上面调用models下 captcha.go中的方法 MakeCaptcha()获取验证码,该captcha.go也就是 一.Captcha验证码功能引入 中captcha.go代码,这是 原来单体架构的做法,访问如下: 现在就要交给 captcha验证码微服务来处理 首先把server/captcha/proto文件夹复制到项目中 封装captcha.go验证码微服务客户端方法
前面章节对于验证码这块儿, 前端和 后台都需要进行 验证码逻辑处理,调用的方法都是models/captcha.go下面的方法,故在进行微服务客户端处理时,也在这里面进行修改 (1).配置consul服务发现
首先,在models下创建initCaptchaConsul.go,配置consul服务发现,以便调用,代码如下: package models//微服务客户端配置: 初始化consul配置,当一个项目中多个微服务时,就很方便了
//建议:一个微服务对应一个客户端,这样好管理import (github.com/go-micro/plugins/v4/registry/consulgo-micro.dev/v4/clientgo-micro.dev/v4/registry
)//CaptchaClient: 全局变量 在外部的包中可以调用
var CaptchaClient client.Client//init 方法: 当程序运行时就会自动执行
func init() {consulRegistry : consul.NewRegistry(//指定微服务的ip: 选择注册服务器地址,默认为本机,也可以选择consul集群中的client,建议一个微服务对应一个consul集群的clientregistry.Addrs(127.0.0.1:8500),)// Create servicesrv : micro.NewService(micro.Registry(consulRegistry),)srv.Init()CaptchaClient srv.Client()
}
在这里,也许没有引入,执行命令:go mod tidy引入对应的包 (2).完善models/captcha.go中的MakeCaptcha获取验证码方法
在该方法中实现调用获取验证码微服务逻辑功能 //调用获取验证码微服务
func MakeCaptcha(height int, width int, length int) (string, string, error) {// Create client: 这里的服务名称需要和服务端注册的名称一致captchaClient : pbCaptcha.NewCaptchaService(captcha, CaptchaClient)// Call service: 创建连接captcha微服务的连接,并传递参数,//该方法最终是请求server端handler中的captcha.go中的MakeCaptcha方法rsp, err : captchaClient.MakeCaptcha(context.Background(), pbCaptcha.MakeCaptchaRequest{Height: int32(height), //验证码高度Width: int32(width), //验证码宽度Length: int32(length), //验证码长度})//判断是否获取成功if err ! nil {log.Fatal(err)}//记录loglog.Info(rsp)//返回return rsp.Id, rsp.B64S, err
}
(3).完善models/captcha.go中的VerifyCaptcha校验验证码方法
在该方法中实现调用校验验证码微服务逻辑功能 //调用校验验证码微服务
func VerifyCaptcha(id string, VerifyValue string) bool {// Create client: 这里的服务名称需要和服务端注册的名称一致captchaClient : pbCaptcha.NewCaptchaService(captcha, CaptchaClient)// Call service: 创建连接captcha微服务的连接,并传递参数,//该方法最终是请求server端handler中的captcha.go中的VerifyCaptcha方法rsp, err : captchaClient.VerifyCaptcha(context.Background(), pbCaptcha.VerifyCaptchaRequest{Id: id, //验证码IdVerifyValue: VerifyValue, //验证码})//判断是否获取成功if err ! nil {log.Fatal(err)}//记录loglog.Info(rsp)//返回return rsp.VerifyResult
}
(4).完整代码如下
package models//验证码属性: https://captcha.mojotv.cn/
import (contextgithub.com/prometheus/common/logpbCaptcha goshop/proto/captcha
)//调用获取验证码微服务
func MakeCaptcha(height int, width int, length int) (string, string, error) {// Create client: 这里的服务名称需要和服务端注册的名称一致captchaClient : pbCaptcha.NewCaptchaService(captcha, CaptchaClient)// Call service: 创建连接captcha微服务的连接,并传递参数,//该方法最终是请求server端handler中的captcha.go中的MakeCaptcha方法rsp, err : captchaClient.MakeCaptcha(context.Background(), pbCaptcha.MakeCaptchaRequest{Height: int32(height), //验证码高度Width: int32(width), //验证码宽度Length: int32(length), //验证码长度})//判断是否获取成功if err ! nil {log.Fatal(err)}//记录loglog.Info(rsp)//返回return rsp.Id, rsp.B64S, err
}//调用校验验证码微服务
func VerifyCaptcha(id string, VerifyValue string) bool {// Create client: 这里的服务名称需要和服务端注册的名称一致captchaClient : pbCaptcha.NewCaptchaService(captcha, CaptchaClient)// Call service: 创建连接captcha微服务的连接,并传递参数,//该方法最终是请求server端handler中的captcha.go中的VerifyCaptcha方法rsp, err : captchaClient.VerifyCaptcha(context.Background(), pbCaptcha.VerifyCaptchaRequest{Id: id, //验证码IdVerifyValue: VerifyValue, //验证码})//判断是否获取成功if err ! nil {log.Fatal(err)}//记录loglog.Info(rsp)//返回return rsp.VerifyResult
} 校验captcha验证码微服务功能
(1).先启动服务端
见前面代码 (2).启动客户端
在项目根目录下运行 :go run main.go,启动项目 (3).访问http://127.0.0.1:8080/admin/captcha
访问 http://127.0.0.1:8080/admin/captcha看看是否显示验证码相关数据 显示了,说明调用了验证码微服务操作 (4).校验验证码微服务操作是否成功
访问后台登录页面,输入用户名,密码,验证码,看看是否成功 好了,captcha验证码微服务客户端操作完成,在这里,上面讲解的是web页面调用captcha验证码微服务功能,下面则讲解Go Web Restfull APi 调用Captcha验证码微服务 四.Go Web Restfull APi 调用Captcha验证码微服务
Go Web Restfull APi 调用Captcha验证码微服务主要是给手机app,微信小程序等提供接口,架构如下 创建一个api的Gin项目,并配置routers
这里直接以上面项目为案例,在routers下创建 apiRouters.go路由文件 构建验证码相关接口,代码如下
在controllers/api/ CaptchaController.go下编写获取验证码,校验验证码相关逻辑,代码如下: package apiimport (contextgithub.com/gin-gonic/gingithub.com/prometheus/common/loggoshop/modelspbCaptcha goshop/proto/captchanet/http
)type CatpchaController struct {
}//获取验证码的接口(调用验证码微服务操作)
func (con CatpchaController) MakeCaptcha(c *gin.Context) {// Create client: 这里的服务名称需要和服务端注册的名称一致captchaClient : pbCaptcha.NewCaptchaService(captcha, models.CaptchaClient)// Call service: 创建连接captcha微服务的连接,并传递参数,//该方法最终是请求server端handler中的captcha.go中的MakeCaptcha方法rsp, err : captchaClient.MakeCaptcha(context.Background(), pbCaptcha.MakeCaptchaRequest{Height: 100, //验证码高度Width: 200, //验证码宽度Length: 4, //验证码长度})//判断是否获取成功if err ! nil {log.Fatal(err)}//记录loglog.Info(rsp)//返回c.JSON(http.StatusOK, gin.H{captchaId: rsp.Id,B64s: rsp.B64S,})
}//校验验证码接口
func (con CatpchaController) VerifyCaptcha(c *gin.Context) {//获取请求参数verifyId : c.PostForm(verifyId)verifyValue : c.PostForm(verifyValue)// Create client: 这里的服务名称需要和服务端注册的名称一致captchaClient : pbCaptcha.NewCaptchaService(captcha, models.CaptchaClient)// Call service: 创建连接captcha微服务的连接,并传递参数,//该方法最终是请求server端handler中的captcha.go中的VerifyCaptcha方法rsp, err : captchaClient.VerifyCaptcha(context.Background(), pbCaptcha.VerifyCaptchaRequest{Id: verifyId, //验证码IdVerifyValue: verifyValue, //验证码})//判断是否获取成功if err ! nil {log.Fatal(err)}//记录loglog.Info(rsp)//返回if rsp.VerifyResult true { // 说明验证通过c.JSON(http.StatusOK, gin.H{message: 验证验证码成功,success: true,})} else {c.JSON(http.StatusOK, gin.H{message: 验证验证码失败,success: false,})}
} 校验api请求是否成功
请求http://127.0.0.1:8080/api/MakeCaptcha,看看是否返回对应的验证码json请求 从上图看得出来,返回了对应验证码的数据的,把 B64s中的数据放入img srcB64s /中,就可以了,展示的图片如下: 然后校验验证码,一般通过postman校验 好了,Go Web Restfull APi 调用Captcha验证码微服务 获取验证码,以及校验验证码api接口操作就完成了 [上一节][golang gin框架] 39.Gin商城项目-微服务实战之微服务架构
[下一节][golang gin框架] 41.Gin商城项目-微服务实战之后台Rbac微服务(用户登录 、Gorm数据库配置单独抽离、 Consul配置单独抽离)