基于gin的golang web开发:实现用户登录
前文分别介绍过了Resty和gin-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开发:实现用户登录的更多相关文章
- 基于gin的golang web开发:永远不要相信用户的输入
作为后端开发者我们要记住一句话:"永远不要相信用户的输入",这里所说的用户可能是人,也可能是另一个应用程序."永远不要相信用户的输入"是安全编码的准则,也就是说 ...
- 基于gin的golang web开发:模型验证
Gin除了模型绑定还提供了模型验证功能.你可以给字段指定特定的规则标签,如果一个字段用binding:"required"标签修饰,在绑定时该字段的值为空,那么将返回一个错误.开发 ...
- 基于gin的golang web开发:集成swagger
在前后端分离的项目维护一份完整且及时更新的api文档会极大的提高我们的工作效率,传统项目中接口文档都是由后端开发手写的,这种文档很难保证及时性,久而久之便失去了参考意义.swagger给我们提供了一种 ...
- 基于gin的golang web开发:docker
Golang天生适合运行在docker容器中,这得益于:Golang的静态编译,当在编译的时候关闭cgo的时候,可以完全不依赖系统环境. 一些基础 测试容器时我们经常需要进入容器查看运行情况,以下命令 ...
- 基于gin的golang web开发:认证利器jwt
JSON Web Token(JWT)是一种很流行的跨域认证解决方案,JWT基于JSON可以在进行验证的同时附带身份信息,对于前后端分离项目很有帮助. eyJhbGciOiJIUzI1NiIsInR5 ...
- 基于gin的golang web开发:Gin技术拾遗
本文是对前几篇文章的一些补充,主要包含两部分:单元测试和实际项目中使用路由的小问题. 拾遗1:单元测试 Golang单元测试要求代码文件以_test结尾,单元测试方法以Test开头,参数为*testi ...
- 基于gin的golang web开发:路由
Gin是一个用Golang编写的HTTP网络框架.它的特点是类似于Martini的API,性能更好.在golang web开发领域是一个非常热门的web框架. 启动一个Gin web服务器 使用下面的 ...
- 基于gin的golang web开发:路由二
在基于gin的golang web开发:路由中我们介绍了Gin的路由和一些获取链接中参数的方法,本文继续介绍其他获取参数的方法. 文件上传 在web开发中文件上传是一个很常见的需求,下面我们来看一下基 ...
- 基于gin的golang web开发:模型绑定
在前两篇文章介绍路由的时候,我们了解到gin可用通过类似DefaultQuery或DefaultPostForm等方法获取到前端提交过来的参数.参数不多的情况下也很好用,但是想想看,如果接口有很多个参 ...
随机推荐
- 使用 JavaScript 操作浏览器历史记录 API
History 是 window 对象中的一个 JavaScript 对象,它包含了关于浏览器会话历史的详细信息.你所访问过的 URL 列表将被像堆栈一样存储起来.浏览器上的返回和前进按钮使用的就是 ...
- zabbix实现自定义自动发现的流程
前言 本章介绍如何去自定义一个zabbix自动发现的整个流程 过程 首先需要在模板当中创建一个自动发现的规则,这个地方只需要一个名称和一个键值,例如 名称:Ceph Cluster Pool Disc ...
- Python_DOM
Dom简介:Js通过标签筛选让html多文件联动 1.找到标签 获取单个元素 docum ent.getElemrntByID('i1') 获取多个元素(列表)document.getElemrnts ...
- SSTI Flask
1.什么是SSTI?什么是Flask? SSTI称为服务端模板注入,主要为Python.Java.PHP的框架在使用渲染函数时,由于代码不规范或者对于用户输入过于信任而导致产生了SSTI.类似于S ...
- 循序渐进VUE+Element 前端应用开发(27)--- 数据表的动态表单设计和数据存储
在我们一些系统里面,有时候会需要一些让用户自定义的数据信息,一般这些可以使用扩展JSON进行存储,不过每个业务表的显示项目可能不一样,因此需要根据不同的表单进行设计,然后进行对应的数据存储.本篇随笔结 ...
- 云计算之路-出海记:建一个免费仓库 Amazon RDS for SQL Server
上周由于园子后院起火,不得不调兵回去救火,出海记暂时停更,这周继续更新,"出海记"记录的是我们在 AWS 上建设博客园海外站的历程. 在这一记中记录的是我们基于 AWS 免费套餐( ...
- 总是说spring难学?来看完这些spring的注解及其解释,真香!
前言 用过spring的人都知道,spring简单的通过注解就可以完成很多事情,但这些东西是如何实现的呢以及如何应用到我们自己的代码中?接下来,让我们一起开启注解的旅程. 1. @Controller ...
- CorelDRAW常用工具之渐变工具
我们在进行宣传单页或者LOGO等等各种平面设计时,颜色的使用是极为重要的一方面.有些新手可能还不知道怎么填充多种颜色的渐变,有的背景色不止2个颜色渐变,而是由多种颜色调成的. 我们在画布上画两个图形, ...
- 如何用ABBYY FineReader提取图片中的文字
作为OCR文字识别软件中的佼佼者,可能大家对于ABBYY FineReader的使用还不熟练,没关系,今天小编就为大家演示,如何用ABBYY FineReader这款文字识别软件,将一张截图中的文字识 ...
- 初学者也能轻松做出好Beat:FPC鼓机使用教程
如果我们想用FL Studio制作一个鼓的声部,这时水果自带的鼓机FPC简直就是我们初学者的福音.因为它的操作比较简单,自带的鼓谱也很丰富,而且我们还可以对鼓的音色做细致的调整,或者是使用自己的采样替 ...