图形化验证码生成和验证
功能介绍
在使用用户名和密码登录功能时,需要填写验证码,验证码是以图形化的方式进行获取和展示的。
验证码使用原理
验证码的使用流程和原理为:在服务器端负责生成图形化验证码,并以数据流的形式供前端访问获取,同时将生成的验证码存储到全局的缓存中,在本案例中,我们使用redis作为全局缓存,并设置缓存失效时间。当用户使用用户名和密码进行登录时,进行验证码验证。验证通过即可继续进行登录。
验证码库安装
借助开源的验证码工具库可以生成验证码。
首先,安装开源的验证码生成库:
go get -u github.com/mojocn/base64Captcha go get github.com/mojocn/base64Captcha@v1.2.2
验证码代码示例
在下载后的base64Captcha库的目录中,可以看到有_example和_example_redis两个目录。第一个example是用于演示生成验证码和验证码的示例代码。
按照示例代码的说明,运行程序并在浏览器进行端口访问:
go run main.go //浏览器中访问:http://localhost:8777
如下图所示:
通过自定义配置,可以选择不同的生成验证码的参数,并刷新验证码,同时还可以对验证码进行验证。
通过exmaple目录下的main.go程序可以看到生成验证码和验证验证码的逻辑,此处不再赘述。
项目集成验证码生成和Redis缓存
通常来说,验证码都是有一定的实效性的,过期验证码也就无效了。
因此,我们考虑在项目中引入Redis作为数据缓存。当验证码生成后,将验证码存放在Redis中,并根据配置文件对Redis进行设置。
安装go-redis库
在项目中使用redis,需要安装go-redis库,可以在https://github.com/go-redis/redis中查看如何下载go-redis和配置。
增加Redis配置
在配置文件app.json中新增redis配置:
"redis_config": { "addr": "127.0.0.1", "port": "6379", "password": "", "db": 0 }
同时,新增RedisConfig结构体定义,如下所示:
type RedisConfig struct { Addr string `json:"addr"` Port string `json:"port"` Password string `json:"password"` Db int `json:"db"` }
Redis初始化操
进行了redis配置以后,需要对redis进行初始化。可以封装redis初始化操作函数如下所示:
type RedisStore struct { redisClient *redis.Client } var Redis *redis.Client func InitRediStore() *RedisStore { config := GetConfig().RedistConfig Redis = redis.NewClient(&redis.Options{ Addr: config.Addr + ":" + config.Port, Password: config.Password, DB: config.Db, }) customeStore := &RedisStore{Redis} base64Captcha.SetCustomStore(customeStore) return customeStore }
同时,为customeStore提供Set和Get两个方法,如下所示:
func (cs *RedisStore) Set(id string, value string) { err := cs.redisClient.Set(id, value, time.Minute*2).Err() if err != nil { log.Println(err.Error()) } } func (cs *RedisStore) Get(id string, clear bool) string { val, err := cs.redisClient.Get(id).Result() if err != nil { toolbox.Error(err.Error()) return "" } if clear { err := cs.redisClient.Del(id).Err() if err != nil { toolbox.Error(err.Error()) return "" } } return val }
对Redis进行初始化和定义完成以后,需要在main中调用一下初始化操作InitRediStore:
func main(){ ... //Redis配置初始化 toolbox.InitRediStore() ... }
验证码生成和验证
本项目中采用的验证码的生成库支持三种验证码,分别是:audio,character和digit。我们选择character类型。
定义Captcha.go文件,实现验证码的生成和验证码函数的定义。在进行验证码生成时,默认提供验证码的配置,并生成验证码后返回给客户端浏览器。如下是生成验证码的函数定义:
//生成验证码 func GenerateCaptchaHandler(ctx *gin.Context) { //图形验证码的默认配置 parameters := base64Captcha.ConfigCharacter{ Height: 60, Width: 240, Mode: 3, ComplexOfNoiseText: 0, ComplexOfNoiseDot: 0, IsUseSimpleFont: true, IsShowHollowLine: false, IsShowNoiseDot: false, IsShowNoiseText: false, IsShowSlimeLine: false, IsShowSineLine: false, CaptchaLen: 4, BgColor: &color.RGBA{ R: 3, G: 102, B: 214, A: 254, }, } captchaId, captcaInterfaceInstance := base64Captcha.GenerateCaptcha("", parameters) base64blob := base64Captcha.CaptchaWriteToBase64Encoding(captcaInterfaceInstance) captchaResult := CaptchaResult{Id: captchaId, Base64Blob: base64blob} // 设置json响应 tool.Success(ctx, map[string]interface{}{ "captcha_result": captchaResult, }) }
验证码接口解析
图形化验证码是用户名和密码登录功能的数据,属于Member模块。因此在MemberController中增加获取验证码的接口解析,如下:
func (mc *MemberController) Router(engine *gin.Engine){ //获取验证码 engine.GET("/api/captcha", mc.captcha) }
测试结果如下,能够正常获取到数据:
验证码的验证
同理,可以对客户端提交的验证码进行验证,具体实现逻辑如下:
//验证验证码是否正确 func CaptchaVerify(r *http.Request) bool { var captchaResult CaptchaResult //接收客户端发送来的请求参数 decoder := json.NewDecoder(r.Body) err := decoder.Decode(&captchaResult) if err != nil { log.Println(err) } defer r.Body.Close() //比较图像验证码 verifyResult := base64Captcha.VerifyCaptcha(captchaResult.Id, captchaResult.VertifyValue) return verifyResult }
用户名密码登录功能开发
功能介绍
上节课已经完成了验证码的生成,本节课来开发用户名、密码和验证码登录功能。
接口和参数解析定义
用户名和密码的登录接口为:
/api/login_pwd
接口请求类型为POST,接口参数有三个:name,pwd,captcha。其中:captcha为验证码。
定义登录参数结构体LoginParam:
//用户名,密码和验证码登录 type LoginParam struct { Name string `json:"name"` //用户名 Password string `json:"pwd"` //密码 Id string `json:"id"`// captchaId 验证码ID Value string `json:"value"` //验证码 }
逻辑控制层实现登录流程控制
方法解析
在MemberController.go文件中,编写方法用于处理用户名密码登录的解析方法如下所示:
func (mc *MemberController) Router(engine *gin.Engine){ engine.POST("/api/login_pwd", mc.nameLogin) }
登录流程编程实现
定义新的func并命名为nameLogin,实现登录流程逻辑控制:
//用户名、密码登录 func (mc *MemberController) nameLogin(context *gin.Context) { //1、登录参数解析 var loginParam param.LoginParam err := toolbox.Decode(context.Request.Body, &loginParam) if err != nil { toolbox.Failed(context, "参数解析失败") return } //2、验证验证码 service := impl.NewMemberService() validate := toolbox.CaptchaVerify(loginParam.Id, loginParam.Value) fmt.Println(validate) if !validate { toolbox.ValidateFailed(context, "验证码不正确, 请重新验证 ") return } //3、登录 member := service.Login(loginParam.Name, loginParam.Password) if member.Id == 0 { toolbox.Failed(context, "登录失败") return } toolbox.Success(context, &member) }
在控制层的nameLogin方法中,主要有3个逻辑处理:
- 1、通过*gin.Context解析请求登录请求携带的参数。
- 2、从携带的参数中得到提交的验证码数据,调用验证码判断验证码方法对验证码进行判断。验证码验证失败或者验证码失效,直接返回登录失败信息。
- 3、使用用户名、密码参数进行登录,判断登录结果。如果登录成功,返回用户登录信息,否则返回登录失败。
Service层实现
在功能服务层的MemberService文件中,定义和实现用户名密码登录的Login方法。详细实现如下:
//用户登录: 如果没有登录过,自动进行登录 func (msi *MemberServiceImpl) Login(name string, password string) *model.Member { dao := impl.NewMemberDao() //1、先查询是否已经存在该用户 member := dao.Query(name, password) if member.Id != 0 { return member } user := model.Member{} user.UserName = name user.Password = toolbox.EncoderSha256(password) user.RegisterTime = time.Now().Unix() result := dao.InsertMember(user) user.Id = result return &user }
在service层的Login方法中,分为两步逻辑判断:
1、先查询是否已经存在该用户,如果该用于已经存在,则直接将查询到的用户信息返回。
2、如果用户不存在,将用户信息作为新记录保存到数据库中,新增一条记录。并返回用户信息。
最后,涉及到操作数据库的两个方法分别是:Query和InsertMember方法。InsertMember方法之前已经编写过,只需要重新编写一个Query方法即可,Query方法实现如下所示:
//根据用户名和密码查询用户记录 func (mdi *MemberDaoImpl) Query(name string, password string) *model.Member { var member model.Member password = toolbox.EncoderSha256(password) _, err := mdi.Where(" user_name = ", name, password).Get(&member) if err != nil { toolbox.Error(err.Error()) return nil } return &member }
Go线上外卖,vue线上外卖
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]