在Gin框架中实现Token令牌认证

什么是token

用户登录成功后,后续操作若需要用户的账号之类的信息一直让前端传递数据这种操作是不安全的,这个时候只需要用户登陆成功之后后端返回一串加密的字符串(token),由前端配置在Header中,这样又安全还能完美的解决问题。下面是生成token,验证token的步骤。

"github.com/dgrijalva/jwt-go" 使用的库

一、定义一个Token结构体

作者的项目token里包含了用户的账号密码及角色,大家按需来定义

Go 复制代码
// Claims Token结构体
type Claims struct {
	Username string `json:"username"`//账号
	Password string `json:"password"`//密码
	Role     string `json:"role"`//角色
	jwt.StandardClaims          //内置结构体,包含token令牌本身的信息
}

二、定义密钥+生成密钥

我定义的密钥长度为七

Go 复制代码
// 定义密钥
var JwtKey = []byte("xlszxjm") //首字母大写,另一个文件中验证方法可以调用
Go 复制代码
// ReleaseToken 生成密钥
func ReleaseToken(username, password, role string) (string, error) {
	expirationTime := time.Now().Add(7 * 24 * time.Hour) //token的有效期是七天
	claims := &Claims{
		Username: username,
		Password: password,
		Role:     role,
		StandardClaims: jwt.StandardClaims{
			ExpiresAt: expirationTime.Unix(), //token的有效期
			IssuedAt:  time.Now().Unix(),     //token发放的时间
			Issuer:    "xxx",                 //作者(可修改)
			Subject:   "user token",          //主题
		},
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString(JwtKey) //根据前面自定义的Jwt秘钥生成token
	tokenString = "Bearer " + tokenString
	if err != nil {
		//返回生成的错误
		return "", err
	}
	//返回成功生成的字符换
	return tokenString, nil
}

三、解析token

Go 复制代码
// ParseToken 解析从前端获取到的token值
func ParseToken(tokenString string) (*jwt.Token, *Claims, error) {
	claims := &Claims{}
	token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
		return JwtKey, nil
	})
	return token, claims, err
}

四、验证token是否合法的中间件

Go 复制代码
func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 获取前端传过来的信息
		tokenString := c.GetHeader("token")
		//验证前端传过来的token格式,不为空,开头为Bearer
		if tokenString == "" || !strings.HasPrefix(tokenString, "Bearer ") {
			response.ResponseError(c, 400)
			c.Abort()
			return
		}
		//验证通过,提取有效部分(除去Bearer)
		tokenString = tokenString[7:] //截取字符
		//解析token
		token, _, err := ParseToken(tokenString)//使用解析token的方法
		//解析失败||解析后的token无效
		if err != nil || !token.Valid {
			response.ResponseError(c, 400)
			c.Abort()
			return
		}
		c.Next()
	}
}

五、通过token获取用户信息

Go 复制代码
// GetUsername 通过token获取username
func GetUsername(tokenString string) (string, error) {
	tokenString = tokenString[7:]
	token, _, err := ParseToken(tokenString)
	if err != nil {
		fmt.Println("GetUsername  ParseToken() err:", err.Error())
		return "", err
	}
	if claims, ok := token.Claims.(*Claims); ok {
		return claims.Username, nil
	}
	return "", nil
}

// GetRole 通过token获取role
func GetRole(tokenString string) (string, error) {
	tokenString = tokenString[7:]
	token, _, err := ParseToken(tokenString)
	if err != nil {
		fmt.Println("GetRole ParseToken() err:", err)
		return "", err
	}
	if claims, ok := token.Claims.(*Claims); ok {
		return claims.Role, nil
	}
	return "", err
}

最后,只需要在用户登录的接口调用生成token的方法,将生成的token返回给前端并配置在Header中,把中间件添加在需要使用到c.GetHeader("token")方法的接口前以防止前端因配置失败出现错误。

相关推荐
福大大架构师每日一题3 小时前
ragflow v0.27.0 发布:Go 后端全面对齐、智能体搜索与知识编译大升级,超全更新解析
开发语言·后端·golang
JavaPub-rodert3 小时前
Go 后台如何同时兼容 MySQL、PostgreSQL、SQLite 和 SQL Server?从 ShiyuAdmin 看 GORM 多数据库适配
数据库·mysql·postgresql·golang·javapub·王仕宇
剩下了什么17 小时前
float32 与 float64 精度陷阱:如何在 Go 中避免错误使用
开发语言·后端·golang
ttwuai1 天前
Go 后台接入 SSO 后菜单正常但接口 403,怎么排查权限链路?
开发语言·后端·golang
PC2005-cloud1 天前
Go学习笔记:基本概念与项目结构——GOPATH、Go Modules 与常用命令
笔记·学习·golang
ttwuai1 天前
Go 后台图片上传到对象存储后,预览 403/404 怎么排查?
开发语言·golang
名字还没想好☜1 天前
Go 1.23 range-over-func 迭代器实战:自定义可迭代类型、提前退出与惰性求值
开发语言·后端·golang·go·迭代器
灯澜忆梦1 天前
【基于GO的Web开发4】html/template 模板语法
后端·golang·html
圣殿骑士-Khtangc1 天前
Go-Kubernetes-Client-go编程从Pod管理到CRD开发
golang
PC2005-cloud1 天前
Go学习笔记:错误处理——没有异常,只有 error
笔记·学习·golang