前面我们使用拦截器可以对想要用户登录的接口进行登录验证拦截,但是具体的代码没有完成,所以本文我们把jwt相关的内容给补充完毕。
1、添加依赖
使用jwt的话,需要使用到jwt-go框架,所以首先需要添加依赖。执行如下的命令
go get -u github.com/dgrijalva/jwt-go
2、编写jwtutils
使用jwt的话,我们一般集成一个自己写的utils类,然后在里面编写jwt的编码和接码相关的方法,因此这里我们在utils目录下创建一个jwtUtils.go文件,示例如下:
完整的代码示例如下:
package utils import ( "errors" "github.com/dgrijalva/jwt-go" "time" ) /* * 这里是我们准备在jwt中存储哪些字段,可以随意添加,这里我们只存储username即可 */ type MyClaims struct { Username string `json:"username"` jwt.StandardClaims } const TokenExpireDuration = time.Hour * 2 var MySecret = []byte("123456") /* * 生成jwt */ func GenToken(username string) (string, error) { // 创建一个我们自己的声明数据结构 c := MyClaims{ username, // 自定义字段 jwt.StandardClaims{ ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间 Issuer: "admin", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) // 使用指定的secret签名并获得完整的编码后的字符串token return token.SignedString(MySecret) } /* * 解码jwt */ func ParseToken(tokenString string) (*MyClaims, error) { // 解析token token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (i interface{}, err error) { return MySecret, nil }) if err != nil { return nil, err } if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { // 校验token return claims, nil } return nil, errors.New("invalid token") }
3、编写登录接口
接下来我们编写一个login的接口,用于用户登录,用户登录成功之后,我们生成jwt token返回给前端,首先我们创建一个request目录,再创建一个loginRequest.go文件,示例如下:
这主要是登录接口我们让前端传递json过来,这里使用loginRequest来接收json参数,loginRequest.go示例代码如下:
package request
type LoginReuqest struct {
Username string `json:"username"`
password string `json:"password"`
}定义了request之后,我们还要定义response,我们希望返回的数据结构是一致的,所以这里创建一个response文件夹,再创建一个baseResponse.go文件,示例如下:
这里统一的返回格式示例是:
{
"Code": 200,
"Msg": "请求成功",
"Data": null
}对应的baseResponse.go示例代码如下:
package response
type BaseResponse struct {
Code int
Msg string
Data any
}然后我们在userController.go里面编写login的方法,示例代码如下:
package controllers
import (
"awesomeProject/config"
"awesomeProject/models"
"awesomeProject/request"
"awesomeProject/response"
"awesomeProject/utils"
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func RegisterUser(c *gin.Context) {
var user models.User
if err := c.ShouldBindJSON(&user); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
log.Println("请求了接口register接口")
config.DB.Create(&user)
c.JSON(http.StatusCreated, user)
}
func LoginUser(c *gin.Context) {
loginRequest := request.LoginReuqest{}
if err := c.ShouldBindJSON(&loginRequest); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
token, err := utils.GenToken(loginRequest.Username)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
rs := response.BaseResponse{
Code: http.StatusOK,
Msg: "请求成功",
Data: token,
}
c.JSON(http.StatusCreated, rs)
}然后把loginUser方法注册到路由里面去:
func SetupRouter() *gin.Engine {
r := gin.Default()
r.POST("/resgister", controllers.RegisterUser)
r.POST("login", controllers.LoginUser)
authorized := r.Group("/api")
authorized.Use(middleware.AuthenticateJWT())
{
authorized.GET("/listgoods", controllers.ListGoods)
}
return r
}这里生成的jwt模块的代码就完成了,咱们运行一下,请求login接口看看,示例图如下:
可以看到成功的生成了jwt的秘钥信息。
4、拦截解析jwt
前面我们生成了jwt,那么比如我们拦截的listgoods接口的时候就需要去拦截jwt的token,并且解析出对应的信息,因此我们需要对middleware包下的jwt.go文件进行改造,改造后的示例代码如下:
package middleware
import (
"awesomeProject/utils"
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func AuthenticateJWT() gin.HandlerFunc {
return func(c *gin.Context) {
tokenString := c.GetHeader("Authorization")
if tokenString == "" {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header required"})
c.Abort()
return
}
chain, err := utils.ParseToken(tokenString)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
c.Abort()
return
}
log.Println("获取到当前登录用户的用户名是:", chain.Username)
c.Set("username", chain.Username)
c.Next()
}
}上面的代码流程是从header头里面获取key为Authorization的jwt信息,然后使用jwt进行解码,解码后就可以获取到Myclaim对象,然后就可以获取到我们存在Myclaim里面的信息了。
这里我们获取到username之后,还可以通过gin.Context对象把用户信息传递下去,在之后的代码里面可以直接在gin.Context对象中获取到用户信息。
接着我们修改下goodsController.go文件
把接口改造一下,完整代码示例如下:
package controllers
import (
"awesomeProject/response"
"github.com/gin-gonic/gin"
"log"
"net/http"
)
func ListGoods(c *gin.Context) {
username, _ := c.Get("username")
log.Println("通过中间件解析获取到的username是:", username)
rs := response.BaseResponse{
http.StatusOK,
"请求成功",
"获取商品列表成功",
}
c.JSON(http.StatusOK, rs)
}最后我们启动项目,进行测试:
可以看到通过jwt的拦截,我们成功的访问了listgoods接口,最后我们再看看日志:
可以看到通过jwt进行解码之后,获取到了我们存储的username值。
以上就是在gin web中添加jwt相关代码的完整案例。
最后附上本案例的源码,登录后即可下载








还没有评论,来说两句吧...