其他分享
首页 > 其他分享> > 使用 Go HTTP 框架 Hertz 进行 JWT 认证

使用 Go HTTP 框架 Hertz 进行 JWT 认证

作者:互联网

Demo 介绍

Demo 下载

git clone https://github.com/cloudwego/hertz-examples.git
cd bizdemo/hertz_jwt

Demo 结构

hertz_jwt
├── Makefile # 使用 hz 命令行工具生成 hertz 脚手架代码
├── biz
│   ├── dal
│   │   ├── init.go 
│   │   └── mysql
│   │       ├── init.go # 初始化数据库连接
│   │       └── user.go # 数据库操作
│   ├── handler
│   │   ├── ping.go
│   │   └── register.go # 用户注册 handler
│   ├── model
│   │   ├── sql
│   │   │   └── user.sql
│   │   └── user.go # 定义数据库模型
│   ├── mw
│   │   └── jwt.go # 初始化 hertz-jwt 中间件
│   ├── router
│   │   └── register.go
│   └── utils
│       └── md5.go # md5 加密
├── docker-compose.yml # mysql 容器环境支持
├── go.mod
├── go.sum
├── main.go # hertz 服务入口
├── readme.md
├── router.go # 路由注册
└── router_gen.go

Demo 分析

下方是这个 demo 的接口列表。

// customizeRegister registers customize routers.
func customizedRegister(r *server.Hertz) {
    r.POST("/register", handler.Register)
    r.POST("/login", mw.JwtMiddleware.LoginHandler)
    auth := r.Group("/auth", mw.JwtMiddleware.MiddlewareFunc())
    auth.GET("/ping", handler.Ping)
}

用户注册

对应 /register 接口,当前 demo 的用户数据通过 gorm 操作 mysql 完成持久化,因此在登陆之前,需要对用户进行注册,注册流程为:

  1. 获取用户名密码和邮箱
  2. 判断用户是否存在
  3. 创建用户

用户登陆(认证)

服务器需要在用户第一次登陆的时候,验证用户账号和密码,并签发 jwt token。

JwtMiddleware, err = jwt.New(&jwt.HertzJWTMiddleware{
    Key:           []byte("secret key"),
    Timeout:       time.Hour,
    MaxRefresh:    time.Hour,
    Authenticator: func(ctx context.Context, c *app.RequestContext) (interface{}, error) {
        var loginStruct struct {
            Account  string `form:"account" json:"account" query:"account" vd:"(len($) > 0 && len($) < 30); msg:'Illegal format'"`
            Password string `form:"password" json:"password" query:"password" vd:"(len($) > 0 && len($) < 30); msg:'Illegal format'"`
        }
        if err := c.BindAndValidate(&loginStruct); err != nil {
            return nil, err
        }
        users, err := mysql.CheckUser(loginStruct.Account, utils2.MD5(loginStruct.Password))
        if err != nil {
            return nil, err
        }
        if len(users) == 0 {
            return nil, errors.New("user already exists or wrong password")
        }
​
        return users[0], nil
    },
    PayloadFunc: func(data interface{}) jwt.MapClaims {
        if v, ok := data.(*model.User); ok {
            return jwt.MapClaims{
                jwt.IdentityKey: v,
            }
        }
        return jwt.MapClaims{}
    },
})

Token 的返回

JwtMiddleware, err = jwt.New(&jwt.HertzJWTMiddleware{
    LoginResponse: func(ctx context.Context, c *app.RequestContext, code int, token string, expire time.Time) {
        c.JSON(http.StatusOK, utils.H{
            "code":    code,
            "token":   token,
            "expire":  expire.Format(time.RFC3339),
            "message": "success",
        })
    },
})

Token 的校验

访问配置了 jwt 中间件的路由时,会经过 jwt token 的校验流程。

标签:数据库,站点,文件,架构,数据,服务器,创建,结束,设置
来源: