脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Go+Vue开发一个线上外卖应用的流程(用户名密码和图形验证码)

Go+Vue开发一个线上外卖应用的流程(用户名密码和图形验证码)

2021-02-01 00:51you-men Golang

这篇文章主要介绍了Go+Vue开发一个线上外卖应用(用户名密码和图形验证码),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

 

图形化验证码生成和验证

 

功能介绍

在使用用户名和密码登录功能时,需要填写验证码,验证码是以图形化的方式进行获取和展示的。

验证码使用原理

验证码的使用流程和原理为:在服务器端负责生成图形化验证码,并以数据流的形式供前端访问获取,同时将生成的验证码存储到全局的缓存中,在本案例中,我们使用redis作为全局缓存,并设置缓存失效时间。当用户使用用户名和密码进行登录时,进行验证码验证。验证通过即可继续进行登录。

验证码库安装

借助开源的验证码工具库可以生成验证码。
首先,安装开源的验证码生成库:

?
1
2
go get -u github.com/mojocn/base64Captcha
go get github.com/mojocn/base64Captcha@v1.2.2

验证码代码示例

在下载后的base64Captcha库的目录中,可以看到有_example和_example_redis两个目录。第一个example是用于演示生成验证码和验证码的示例代码。

按照示例代码的说明,运行程序并在浏览器进行端口访问:

?
1
2
go run main.go
//浏览器中访问:http://localhost:8777

如下图所示:

Go+Vue开发一个线上外卖应用的流程(用户名密码和图形验证码)

通过自定义配置,可以选择不同的生成验证码的参数,并刷新验证码,同时还可以对验证码进行验证。

通过exmaple目录下的main.go程序可以看到生成验证码和验证验证码的逻辑,此处不再赘述。

 

项目集成验证码生成和Redis缓存

 

通常来说,验证码都是有一定的实效性的,过期验证码也就无效了。

因此,我们考虑在项目中引入Redis作为数据缓存。当验证码生成后,将验证码存放在Redis中,并根据配置文件对Redis进行设置。

安装go-redis库

在项目中使用redis,需要安装go-redis库,可以在https://github.com/go-redis/redis中查看如何下载go-redis和配置。

增加Redis配置

在配置文件app.json中新增redis配置:

?
1
2
3
4
5
6
"redis_config": {
 "addr": "127.0.0.1",
 "port": "6379",
 "password": "",
 "db": 0
}

同时,新增RedisConfig结构体定义,如下所示:

?
1
2
3
4
5
6
type RedisConfig struct {
    Addr string `json:"addr"`
    Port string `json:"port"`
    Password string `json:"password"`
    Db int `json:"db"`
}

Redis初始化操

进行了redis配置以后,需要对redis进行初始化。可以封装redis初始化操作函数如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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两个方法,如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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:

?
1
2
3
4
5
6
func main(){
 ...
 //Redis配置初始化
     toolbox.InitRediStore()
 ...
}

验证码生成和验证

本项目中采用的验证码的生成库支持三种验证码,分别是:audio,character和digit。我们选择character类型。

定义Captcha.go文件,实现验证码的生成和验证码函数的定义。在进行验证码生成时,默认提供验证码的配置,并生成验证码后返回给客户端浏览器。如下是生成验证码的函数定义:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//生成验证码
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中增加获取验证码的接口解析,如下:

?
1
2
3
4
func (mc *MemberController) Router(engine *gin.Engine){
 //获取验证码
 engine.GET("/api/captcha", mc.captcha)
}

测试结果如下,能够正常获取到数据:

Go+Vue开发一个线上外卖应用的流程(用户名密码和图形验证码)

验证码的验证

同理,可以对客户端提交的验证码进行验证,具体实现逻辑如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//验证验证码是否正确
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
}

 

用户名密码登录功能开发

 

功能介绍

上节课已经完成了验证码的生成,本节课来开发用户名、密码和验证码登录功能。

接口和参数解析定义

用户名和密码的登录接口为:

?
1
/api/login_pwd

接口请求类型为POST,接口参数有三个:name,pwd,captcha。其中:captcha为验证码。

定义登录参数结构体LoginParam:

?
1
2
3
4
5
6
7
//用户名,密码和验证码登录
type LoginParam struct {
    Name  string    `json:"name"` //用户名
    Password string    `json:"pwd"` //密码
    Id  string    `json:"id"`// captchaId 验证码ID
    Value string    `json:"value"` //验证码
}

逻辑控制层实现登录流程控制

方法解析

在MemberController.go文件中,编写方法用于处理用户名密码登录的解析方法如下所示:

?
1
2
3
func (mc *MemberController) Router(engine *gin.Engine){
 engine.POST("/api/login_pwd", mc.nameLogin)
}

 

登录流程编程实现

 

定义新的func并命名为nameLogin,实现登录流程逻辑控制:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//用户名、密码登录
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方法。详细实现如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//用户登录: 如果没有登录过,自动进行登录
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方法实现如下所示:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//根据用户名和密码查询用户记录
func (mdi *MemberDaoImpl) Query(name string, password string) *model.Member {
    var member model.Member
 
    password = toolbox.EncoderSha256(password)
 
    _, err := mdi.Where(" user_name = ? and password = ? ", name, password).Get(&member)
    if err != nil {
        toolbox.Error(err.Error())
        return nil
    }
 
    return &member
}

到此这篇关于Go+Vue开发一个线上外卖应用(用户名密码和图形验证码)的文章就介绍到这了,更多相关Go线上外卖内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/you-men/p/13918316.html

延伸 · 阅读

精彩推荐
  • Golanggolang如何使用struct的tag属性的详细介绍

    golang如何使用struct的tag属性的详细介绍

    这篇文章主要介绍了golang如何使用struct的tag属性的详细介绍,从例子说起,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看...

    Go语言中文网11352020-05-21
  • Golanggo日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    SmallQinYan12302021-02-02
  • Golanggolang 通过ssh代理连接mysql的操作

    golang 通过ssh代理连接mysql的操作

    这篇文章主要介绍了golang 通过ssh代理连接mysql的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    a165861639710342021-03-08
  • Golanggolang json.Marshal 特殊html字符被转义的解决方法

    golang json.Marshal 特殊html字符被转义的解决方法

    今天小编就为大家分享一篇golang json.Marshal 特殊html字符被转义的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    李浩的life12792020-05-27
  • GolangGolang通脉之数据类型详情

    Golang通脉之数据类型详情

    这篇文章主要介绍了Golang通脉之数据类型,在编程语言中标识符就是定义的具有某种意义的词,比如变量名、常量名、函数名等等,Go语言中标识符允许由...

    4272021-11-24
  • GolangGolang中Bit数组的实现方式

    Golang中Bit数组的实现方式

    这篇文章主要介绍了Golang中Bit数组的实现方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    天易独尊11682021-06-09
  • Golanggo语言制作端口扫描器

    go语言制作端口扫描器

    本文给大家分享的是使用go语言编写的TCP端口扫描器,可以选择IP范围,扫描的端口,以及多线程,有需要的小伙伴可以参考下。 ...

    脚本之家3642020-04-25
  • Golanggolang的httpserver优雅重启方法详解

    golang的httpserver优雅重启方法详解

    这篇文章主要给大家介绍了关于golang的httpserver优雅重启的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,...

    helight2992020-05-14