基于 go-zero 轻松实现 JWT 认证 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
kevinwan
V2EX    Go 编程语言

基于 go-zero 轻松实现 JWT 认证

  •  
  •   kevinwan 2020-09-22 17:51:32 +08:00 1723 次点击
    这是一个创建于 1913 天前的主题,其中的信息可能已经有所发展或是发生改变。

    关于 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

    1. 在 api 文件中通过jwt: JwtAuth标记的 service 表示激活了 jwt 认证。
    2. 可以阅读 rest/handler/authhandler.go 文件了解服务器 jwt 实现。
    3. 修改 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. 微信交流群

    微信交流群

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2790 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 14:26 PVG 22:26 LAX 06:26 JFK 09:26
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86