JWT
概述
在 go-zero 中,我们通过 api 语言来声明 HTTP 服务,然后通过 goctl 生成 HTTP 服务代码,在之前我们系统性的介绍了 API 规范。
在 HTTP 服务开发中,服务认证也是经常会用到的一个功能,本文档将介绍如何在 api 文件中声明中间件。
JWT
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间传递声明式信息。它是一种基于JSON的轻量级的身份验证和授权机制,用于在客户端和服务器之间安全地传输信息。
更多关于 jwt 的文档请参考
我们来看一下在 api 文件中如何声明开启 jwt 认证
syntax = "v1"
type LoginReq {
Username string `json:"username"`
Password string `json:"password"`
}
type LoginResp {
ID string `json:"id"`
Name string `json:"name"`
}
type UserInfoReq {
ID string `json:"id"`
}
type UserInfoResp {
Name string `json:"name"`
}
service user-api {
@handler login
post /user/login (LoginReq) returns (LoginResp)
}
@server (
jwt: Auth // 开启 jwt 认证
)
service user-api {
@handler userInfo
post /user/info (UserInfoReq) returns (UserInfoResp)
}
在上文中,我们通过在 @server
中来通过 jwt
关键字声明了开启 jwt 认证,且该 jwt 认证仅对其对应的路由有用,如上文中 jwt 仅对
/user/info
生效,对 /user/login
是不生效的,我们使用 Auth
来作为 jwt 的值,其在经过 goctl
进行代码生成后会转成
对应 jwt 配置。
下面简单看一下生成的 jwt 代码:
- config.go
- routes.go
package config
import "github.com/zeromicro/go-zero/rest"
type Config struct {
rest.RestConf
Auth struct {// JWT 认证需要的密钥和过期时间配置
AccessSecret string
AccessExpire int64
}
}
Config
结构体中的 Auth 字段就是我们通过在 api 语法文件中声明的值,这是代码生成后的结果。
// Code generated by goctl. DO NOT EDIT.
package handler
import (
"net/http"
"go-zero-demo/user/internal/svc"
"github.com/zeromicro/go-zero/rest"
)
func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/user/login",
Handler: loginHandler(serverCtx),
},
},
)
server.AddRoutes(
[]rest.Route{
{
Method: http.MethodPost,
Path: "/user/info",
Handler: userInfoHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.Auth.AccessSecret),
)
}
在上文中,我们可以看到,我们声明的 jwt
其实在生成代码后通过 rest.WithJwt
来声明进行 jwt 认证了。
注意
代码生成后的 jwt 认证,框架只做了服务端逻辑,对于 jwt token 的生成及 refresh token 仍需要开发者自行实现。
载体信息获取
jwt 通常可以携带一些自定义信息,比如 server 端生成 jwt key 时添加了 custom-key
值,go-zero 在解析后会将所有载体放到 context 中,开发者可以
通过如下示例获取载体信息。
func (l *UserInfoLogic) UserInfo(req *types.UserInfoReq) (resp *types.UserInfoResp, err error) {
// 获取 jwt 载体信息
value:=l.ctx.Value("custom-key")
return
}