基于Golang Go语言中的go-zero轻松实现JWT认证
基于Golang Go语言中的go-zero轻松实现JWT认证
关于 JWT 是什么,大家可以看看官网,一句话介绍下:是可以实现服务器无状态的鉴权认证方案,也是目前最流行的跨域认证解决方案。
要实现 JWT 认证,我们需要分成如下两个步骤
- 客户端获取 JWT token 。
- 服务器对客户端带来的 JWT token 认证。
1. 客户端获取 JWT Token
我们定义一个协议供客户端调用获取 JWT token,我们新建一个目录 jwt 然后在目录中执行 goctl api -o jwt.api
,将生成的 jwt.api 改成如下:
type JwtTokenRequest struct {
}
type JwtTokenResponse struct {
AccessToken string json:"access_token"
AccessExpire int64 json:"access_expire"
RefreshAfter int64 json:"refresh_after"
// 建议客户端刷新 token 的绝对时间
}
type GetUserRequest struct {
UserId string json:"userId"
}
type GetUserResponse struct {
Name string json:"name"
}
service jwt-api {
@server(
handler: JwtHandler
)
post /user/token(JwtTokenRequest) returns (JwtTokenResponse)
}
@server(
jwt: JwtAuth
)
service jwt-api {
@server(
handler: GetUserHandler
)
post /user/info(GetUserRequest) returns (GetUserResponse)
}
在服务 jwt 目录中执行:goctl api go -api jwt.api -dir .
打开 jwtlogic.go 文件,修改 func (l *JwtLogic) Jwt(req types.JwtTokenRequest) (*types.JwtTokenResponse, error) {
方法如下:
func (l *JwtLogic) Jwt(req types.JwtTokenRequest) (*types.JwtTokenResponse, error) {
var accessExpire = l.svcCtx.Config.JwtAuth.AccessExpire
now := time.Now().Unix()
accessToken, err := l.GenToken(now, l.svcCtx.Config.JwtAuth.AccessSecret, nil, accessExpire)
if err != nil {
return nil, err
}
return &types.JwtTokenResponse{
AccessToken: accessToken,
AccessExpire: now + accessExpire,
RefreshAfter: now + accessExpire/2,
}, nil
}
func (l *JwtLogic) GenToken(iat int64, secretKey string, payloads map[string]interface{}, seconds int64) (string, error) {
claims := make(jwt.MapClaims)
claims[“exp”] = iat + seconds
claims[“iat”] = iat
for k, v := range payloads {
claims[k] = v
}
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(secretKey))
}
在启动服务之前,我们需要修改 etc/jwt-api.yaml 文件如下:
Name: jwt-api
Host: 0.0.0.0
Port: 8888
JwtAuth:
AccessSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AccessExpire: 604800
启动服务器,然后测试下获取到的 token 。
➜ curl --location --request POST '127.0.0.1:8888/user/token'
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDEyNjE0MjksImlhdCI6MTYwMDY1NjYyOX0.6u_hpE_4m5gcI90taJLZtvfekwUmjrbNJ-5saaDGeQc","access_expire":1601261429,"refresh_after":1600959029}
2. 服务器验证 JWT token
- 在 api 文件中通过
jwt: JwtAuth
标记的 service 表示激活了 jwt 认证。 - 可以阅读 rest/handler/authhandler.go 文件了解服务器 jwt 实现。
- 修改 getuserlogic.go 如下:
func (l *GetUserLogic) GetUser(req types.GetUserRequest) (*types.GetUserResponse, error) {
return &types.GetUserResponse{Name: "kim"}, nil
}
- 我们先不带 JWT Authorization header 请求头测试下,返回 http status code 是 401,符合预期。
➜ curl -w "\nhttp: %{http_code} \n" --location --request POST '127.0.0.1:8888/user/info' \
--header 'Content-Type: application/json' \
--data-raw '{
"userId": "a"
}'
http: 401
- 加上 Authorization header 请求头测试。
➜ curl -w "\nhttp: %{http_code} \n" --location --request POST '127.0.0.1:8888/user/info' \
--header 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDEyNjE0MjksImlhdCI6MTYwMDY1NjYyOX0.6u_hpE_4m5gcI90taJLZtvfekwUmjrbNJ-5saaDGeQc' \
--header 'Content-Type: application/json' \
--data-raw '{
"userId": "a"
}'
{"name":"kim"}
http: 200
基于 go-zero 的 JWT 认证完成,在真实生产环境部署时候,AccessSecret, AccessExpire, RefreshAfter 根据业务场景通过配置文件配置,RefreshAfter 是告诉客户端什么时候该刷新 JWT token 了,一般都需要设置过期时间前几天。
8. 项目地址
https://github.com/tal-tech/go-zero
9. 微信交流群
更多关于基于Golang Go语言中的go-zero轻松实现JWT认证的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于基于Golang Go语言中的go-zero轻松实现JWT认证的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,利用go-zero框架实现JWT(JSON Web Tokens)认证是一种高效且常见的方法。go-zero作为一个微服务框架,提供了丰富的组件和工具,使得集成JWT认证变得相对简单。
首先,你需要引入JWT相关的库,如github.com/dgrijalva/jwt-go
,这个库提供了JWT的创建、解析和验证等功能。
接着,在go-zero的服务中,你可以创建一个中间件来处理JWT的验证。中间件会在每个请求到达业务逻辑之前,检查请求头中是否包含有效的JWT。如果JWT有效,中间件会将用户信息(如用户ID)提取出来,并附加到请求的上下文中,供后续的业务逻辑使用。
为了生成JWT,你需要在用户登录或其他需要认证的场景中,创建一个包含用户信息和过期时间的JWT字符串,并将其返回给客户端。客户端在后续的请求中,需要将这个JWT字符串放在请求头中,以便服务器进行验证。
此外,go-zero还提供了API网关组件,你可以将JWT验证的逻辑放在网关层,这样所有的微服务都可以共享这个认证机制,而无需在每个服务中都实现一遍。
总的来说,利用go-zero框架和JWT库,你可以轻松地实现一个安全、高效的认证机制。这不仅提高了系统的安全性,还简化了认证逻辑的实现和维护。如果你需要更详细的实现步骤或示例代码,可以参考go-zero的官方文档或社区资源。