基于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等方法获取到前端提交过来的参数.参数不多的情况下也很好用,但是想想看,如果接口有很多个参 ...
随机推荐
- 从ceph对象中提取RBD中的指定文件
前言 之前有个想法,是不是有办法找到rbd中的文件与对象的关系,想了很久但是一直觉得文件系统比较复杂,在fs 层的东西对ceph来说是透明的,并且对象大小是4M,而文件很小,可能在fs层进行了合并,应 ...
- Java POI 导出带有图片的word
1. 引入maven ,具体可以上github看一下,这里做简单的说明,是一个大神封装了一下 官方提供的语法 文本语法是 {{Text}} 图片语法是{{@Image}} 其他的自己去看官方文档 &l ...
- CSP-J 2020题解
CSP-J 2020题解 本次考试还是很有用的,至少把我浇了一盆冷水. 当使用民间数据自测的时候,我就自闭了. 估分是320,但有些比较低级的错误直接少掉80. 而且这套题应该上350才正常吧,也不是 ...
- 推荐一个学习SQL Server基本语法及其他编程的网站
菜鸟们的练习场 1.领先的 Web 技术教程 在 w3school,你可以找到你所需要的所有的网站建设教程. 从基础的 HTML 到 CSS,乃至进阶的XML.SQL.JS.PHP 和 ASP.NET ...
- 03、MyBatis 映射文件
1.XML映射器 2.select Select元素来定义查询操作 Id:唯一标识符 - 用来引用这条语句,需要和接口的方法名一致 parameterType:参数类型 - 可以不传,MyBatis会 ...
- kali 2020.1 更新源,并安装docker
先说一句浙大牛逼!!!装个docker折腾了半天,测了半天只有浙大的更新源能用,完美不报错!清华阿里什么的更新源都是渣渣. deb http://mirrors.zju.edu.cn/kali kal ...
- 企业级工作流解决方案(八)--微服务Tcp消息传输模型之服务端处理
服务端启动 服务端启动主要做几件事情,1. 从配置文件读取服务配置(主要是服务监听端口和编解码配置),2. 注册编解码器工厂,3. 启动dotnetty监听端口,4. 读取配置文件,解析全局消息处理模 ...
- 交换机通过Loopback Detection检测(设备所在网络环路)
组网图形 Loopback Detection简介 见上篇文章(详情见),不再赘述. 组网需求 如图1所示,某小型企业采用二层组网,所属VLAN为100.由于人员流动性大,网络拓扑变动频繁,变动往往 ...
- 你还在 if...else?代码这样写才好看!
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 前后端分离之前端vue
npm install --global vue-clivue init webpack my-project cd my-project npm install npm run dev ...