前文分别介绍过了Restygin-jwt两个包,Resty是一个HTTP和REST客户端,gin-jwt是一个实现了JWT的Gin中间件。本文将使用这两个包来实现一个简单的用户登录功能。

环境准备

实现登录功能之前要提前准备一个用于查询用户是否存在的服务。访问服务http://127.0.0.1:18081/users?username=root时返回用户root的相关信息

{
"total": 1,
"data": [
{
"id": 1,
"username": "root",
"password": "CGUx1FN++xS+4wNDFeN6DA==",
"nickname": "超级管理员",
"mobile": "13323232323"
}
]
}

返回结果中password字段AES加密后的结果。当参数username传入其他字符串时返回null

{
"total": 0,
"data": null
}

好了准备工作到此结束,下面来看一下如何实现登录功能。

实现认证

首先实现调用查询用户服务的方法。

func FindUser(userName string) (user sysUser.SysUser, err error) {
client := resty.New().SetRetryCount(3)
resp, err := client.R().
SetQueryParams(map[string]string{
"username": userName,
}).
SetResult(&PagedUser{}).
Get("http://127.0.0.1:18081/users")
if err != nil {
log.Panicln("FindUser err: ", err.Error())
}
response := resp.Result().(*PagedUser)
if response.Total == 1 {
user = response.Data[0]
return
}
err = errors.New("用户不存在")
return
}

这里我们创建了一个Resty客户端,并设置了3次重试,依照服务的要求传入username参数,然后通过Total值判断用户是否存在,用户存在的话返回用户信息,否则返回错误。

接下来我们实现有关jwt验证的部分。

var identityKey = "id"

type login struct {
Username string `form:"username" json:"username" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
} type User struct {
Id int
UserName string
NickName string
} func JwtMiddleware() (authMiddleware *jwt.GinJWTMiddleware, err error) {
authMiddleware, err = jwt.New(&jwt.GinJWTMiddleware{
Realm: "test zone",
Key: []byte("secret key"),
Timeout: time.Hour,
MaxRefresh: time.Hour,
IdentityKey: identityKey,
PayloadFunc: func(data interface{}) jwt.MapClaims {
if v, ok := data.(*User); ok {
return jwt.MapClaims{
identityKey: v.UserName,
}
}
return jwt.MapClaims{}
},
IdentityHandler: func(c *gin.Context) interface{} {
claims := jwt.ExtractClaims(c)
return &User{
UserName: claims[identityKey].(string),
}
},
Authenticator: func(c *gin.Context) (interface{}, error) {
var loginVals login
if err := c.ShouldBind(&loginVals); err != nil {
return "", jwt.ErrMissingLoginValues
}
userID := loginVals.Username
password := loginVals.Password user, err := http_service.FindUser(userID)
if err != nil {
return nil, jwt.ErrFailedAuthentication
} encrypt := utils.PasswordEncrypt(password, userID)
if encrypt != user.Password.String {
return nil, jwt.ErrFailedAuthentication
} return &User{
Id: user.Id,
UserName: user.Username.String,
NickName: user.Nickname.String,
}, nil
},
Authorizator: func(data interface{}, c *gin.Context) bool {
if v, ok := data.(*User); ok && v.UserName == "admin" {
return true
} return false
},
Unauthorized: func(c *gin.Context, code int, message string) {
c.JSON(code, gin.H{
"code": code,
"message": message,
})
},
TokenLookup: "header: Authorization, query: token, cookie: jwt_middleware",
TokenHeadName: "Bearer",
TimeFunc: time.Now,
})
return
}

以上代码在基于gin的golang web开发:认证利器jwt一文中有详细的解释,我们重点来看一下用户验证的部分:Authenticator

方法ShouldBind对参数进行模型绑定,不熟悉模型绑定的话可以查看前文基于gin的golang web开发:模型绑定。然后调用FindUser方法检查用户是否存在,如果用户存在的话还需要验证一下用户密码是否正确。全部验证通过返回User结构体,进入gin-jwt的后续流程。

最后一步在Gin中增加用户登录路由。

func main() {
r := gin.Default() authMiddleware, err := JwtMiddleware()
if err != nil {
log.Fatal("JWT Error:" + err.Error())
} errInit := authMiddleware.MiddlewareInit() if errInit != nil {
log.Fatal("authMiddleware.MiddlewareInit() Error:" + errInit.Error())
} r.POST("/login", authMiddleware.LoginHandler) r.Run(":8090")
}

大功告成,现在调用/login接口,并提供正确的用户名和密码,不出意外的话会得到一个成功的JSON,里面包含了验证通过的JWT。

文章出处:基于gin的golang web开发:实现用户登录

基于gin的golang web开发:实现用户登录的更多相关文章

  1. 基于gin的golang web开发:永远不要相信用户的输入

    作为后端开发者我们要记住一句话:"永远不要相信用户的输入",这里所说的用户可能是人,也可能是另一个应用程序."永远不要相信用户的输入"是安全编码的准则,也就是说 ...

  2. 基于gin的golang web开发:模型验证

    Gin除了模型绑定还提供了模型验证功能.你可以给字段指定特定的规则标签,如果一个字段用binding:"required"标签修饰,在绑定时该字段的值为空,那么将返回一个错误.开发 ...

  3. 基于gin的golang web开发:集成swagger

    在前后端分离的项目维护一份完整且及时更新的api文档会极大的提高我们的工作效率,传统项目中接口文档都是由后端开发手写的,这种文档很难保证及时性,久而久之便失去了参考意义.swagger给我们提供了一种 ...

  4. 基于gin的golang web开发:docker

    Golang天生适合运行在docker容器中,这得益于:Golang的静态编译,当在编译的时候关闭cgo的时候,可以完全不依赖系统环境. 一些基础 测试容器时我们经常需要进入容器查看运行情况,以下命令 ...

  5. 基于gin的golang web开发:认证利器jwt

    JSON Web Token(JWT)是一种很流行的跨域认证解决方案,JWT基于JSON可以在进行验证的同时附带身份信息,对于前后端分离项目很有帮助. eyJhbGciOiJIUzI1NiIsInR5 ...

  6. 基于gin的golang web开发:Gin技术拾遗

    本文是对前几篇文章的一些补充,主要包含两部分:单元测试和实际项目中使用路由的小问题. 拾遗1:单元测试 Golang单元测试要求代码文件以_test结尾,单元测试方法以Test开头,参数为*testi ...

  7. 基于gin的golang web开发:路由

    Gin是一个用Golang编写的HTTP网络框架.它的特点是类似于Martini的API,性能更好.在golang web开发领域是一个非常热门的web框架. 启动一个Gin web服务器 使用下面的 ...

  8. 基于gin的golang web开发:路由二

    在基于gin的golang web开发:路由中我们介绍了Gin的路由和一些获取链接中参数的方法,本文继续介绍其他获取参数的方法. 文件上传 在web开发中文件上传是一个很常见的需求,下面我们来看一下基 ...

  9. 基于gin的golang web开发:模型绑定

    在前两篇文章介绍路由的时候,我们了解到gin可用通过类似DefaultQuery或DefaultPostForm等方法获取到前端提交过来的参数.参数不多的情况下也很好用,但是想想看,如果接口有很多个参 ...

随机推荐

  1. 11Linux之软件包管理

    11Linux之软件包管理 目录 11Linux之软件包管理 11 软件包管理 11.1 软件包介绍 11.1.1 编程语言分类 11.1.2 三种安装包 11.2 rpm包管理 11.2.1 rpm ...

  2. Linux_Python版本控制

    第1步:更新gcc,因为gcc版本太老会导致新版本python包编译不成功 复制代码代码如下: yum -y install gcc 系统会自动下载并安装或更新,等它自己结束 第2步:安装wget,这 ...

  3. 《Machine Learning in Action》—— 小朋友,快来玩啊,决策树呦

    <Machine Learning in Action>-- 小朋友,快来玩啊,决策树呦 在上篇文章中,<Machine Learning in Action>-- Taoye ...

  4. Seay源代码审计系统使用

    Seay源代码审计系统简介 Seay源代码审计系统使用 如何使用"Seay源代码审计系统"扫描源代码漏洞 Seay源代码审计系统下载安装 github-Seay源代码审计系统

  5. Android RFID调试总结

    调试了包括驱动,jni层,当然也熟悉了下应用层.    1. 驱动层包括修改:        device/eastaeon/aeon6735_65c_l/init.project.rc    //去 ...

  6. Flask端点概念

    Flask要点理解 路由端点 通常,我们使用app.route()装饰器将视图函数注册为路由.如果不使用该装饰器,也可以采用app.add_url_rule(rule, endpoint, view_ ...

  7. 2017年第八届蓝桥杯【C++省赛B组】B、C、D、H 题解

    可能因为我使用暴力思维比较少,这场感觉难度不低. B. 等差素数列 #暴力 #枚举 题意 类似:\(7,37,67,97,127,157\) 这样完全由素数组成的等差数列,叫等差素数数列. 上边的数列 ...

  8. Eclipse中get/set方法自动生成

    代码中点击右键(快捷键Ctrl+Alt+S) ->Source ->Generate Getters and Setters... ->全选(或选择需要生成的字段/方法) 动图: 静 ...

  9. python中字符串的编码和解码

    1. 常用的编码 ASCII:只能表示一些字母,数字和特殊的字符,占一个字节 GBK:国家简体中文字符集和繁体字符集,兼容ASCII,占两个字节 Unicode:能够表示全世界上所有的字符,Unico ...

  10. 浅谈代理模式与java中的动态代理

    代理模式的定义: 代理模式是一个使用律非常高的模式,定义如下: 为其他对象提供一种代理,以控制对这个对象的访问. 类图: 简单的静态代理: public interface IRunner{ //这是 ...