{"id":159773,"date":"2020-09-21T09:22:29","date_gmt":"2020-09-21T01:22:29","guid":{"rendered":"http:\/\/4563.org\/?p=159773"},"modified":"2020-09-21T09:22:29","modified_gmt":"2020-09-21T01:22:29","slug":"%e5%9f%ba%e4%ba%8e-go-zero-%e8%bd%bb%e6%9d%be%e5%ae%9e%e7%8e%b0-jwt-%e8%ae%a4%e8%af%81","status":"publish","type":"post","link":"http:\/\/4563.org\/?p=159773","title":{"rendered":"\u57fa\u4e8e go-zero \u8f7b\u677e\u5b9e\u73b0 JWT \u8ba4\u8bc1"},"content":{"rendered":"<div>\n<div>\n<div>\n<h1>                  \u57fa\u4e8e go-zero \u8f7b\u677e\u5b9e\u73b0 JWT \u8ba4\u8bc1               <\/h1>\n<p> <\/p>\n<div>\n<div> <span>\u8cc7\u6df1\u5927\u4f6c : kevinwan <\/span>  <span><i><\/i> 4<\/span> <\/div>\n<div> <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<\/p><\/div>\n<div isfirst=\"1\"> <\/p>\n<p>\u5173\u4e8e JWT \u662f\u4ec0\u4e48\uff0c\u5927\u5bb6\u53ef\u4ee5\u770b\u770b\u5b98\u7f51\uff0c\u4e00\u53e5\u8bdd\u4ecb\u7ecd\u4e0b\uff1a\u662f\u53ef\u4ee5\u5b9e\u73b0\u670d\u52a1\u5668\u65e0\u72b6\u6001\u7684\u9274\u6743\u8ba4\u8bc1\u65b9\u6848\uff0c\u4e5f\u662f\u76ee\u524d\u6700\u6d41\u884c\u7684\u8de8\u57df\u8ba4\u8bc1\u89e3\u51b3\u65b9\u6848\u3002<\/p>\n<p>\u8981\u5b9e\u73b0 JWT \u8ba4\u8bc1\uff0c\u6211\u4eec\u9700\u8981\u5206\u6210\u5982\u4e0b\u4e24\u4e2a\u6b65\u9aa4<\/p>\n<ul>\n<li>\u5ba2\u6237\u7aef\u83b7\u53d6 JWT token \u3002<\/li>\n<li>\u670d\u52a1\u5668\u5bf9\u5ba2\u6237\u7aef\u5e26\u6765\u7684 JWT token \u8ba4\u8bc1\u3002<\/li>\n<\/ul>\n<h2>1. \u5ba2\u6237\u7aef\u83b7\u53d6 JWT Token<\/h2>\n<p>\u6211\u4eec\u5b9a\u4e49\u4e00\u4e2a\u534f\u8bae\u4f9b\u5ba2\u6237\u7aef\u8c03\u7528\u83b7\u53d6 JWT token\uff0c\u6211\u4eec\u65b0\u5efa\u4e00\u4e2a\u76ee\u5f55 jwt \u7136\u540e\u5728\u76ee\u5f55\u4e2d\u6267\u884c <code>goctl api -o jwt.api<\/code>\uff0c\u5c06\u751f\u6210\u7684 jwt.api \u6539\u6210\u5982\u4e0b\uff1a<\/p>\n<pre><code>type JwtTokenRequest struct { }  type JwtTokenResponse struct {   AccessToken  string `json:\"access_token\"`   AccessExpire int64  `json:\"access_expire\"`   RefreshAfter int64  `json:\"refresh_after\"` \/\/ \u5efa\u8bae\u5ba2\u6237\u7aef\u5237\u65b0 token \u7684\u7edd\u5bf9\u65f6\u95f4 }  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) } <\/code><\/pre>\n<p>\u5728\u670d\u52a1 jwt \u76ee\u5f55\u4e2d\u6267\u884c\uff1a<code>goctl api go -api jwt.api -dir .<\/code> \u6253\u5f00 jwtlogic.go \u6587\u4ef6\uff0c\u4fee\u6539 <code>func (l *JwtLogic) Jwt(req types.JwtTokenRequest) (*types.JwtTokenResponse, error) {<\/code> \u65b9\u6cd5\u5982\u4e0b\uff1a<\/p>\n<pre><code> 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 &amp;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)) } <\/code><\/pre>\n<p>\u5728\u542f\u52a8\u670d\u52a1\u4e4b\u524d\uff0c\u6211\u4eec\u9700\u8981\u4fee\u6539 etc\/jwt-api.yaml \u6587\u4ef6\u5982\u4e0b\uff1a<\/p>\n<pre><code>Name: jwt-api Host: 0.0.0.0 Port: 8888 JwtAuth:   AccessSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxx   AccessExpire: 604800 <\/code><\/pre>\n<p>\u542f\u52a8\u670d\u52a1\u5668\uff0c\u7136\u540e\u6d4b\u8bd5\u4e0b\u83b7\u53d6\u5230\u7684 token \u3002<\/p>\n<pre><code>\u279c 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} <\/code><\/pre>\n<h2>2. \u670d\u52a1\u5668\u9a8c\u8bc1 JWT token<\/h2>\n<ol>\n<li>\u5728 api \u6587\u4ef6\u4e2d\u901a\u8fc7<code>jwt: JwtAuth<\/code>\u6807\u8bb0\u7684 service \u8868\u793a\u6fc0\u6d3b\u4e86 jwt \u8ba4\u8bc1\u3002<\/li>\n<li>\u53ef\u4ee5\u9605\u8bfb rest\/handler\/authhandler.go \u6587\u4ef6\u4e86\u89e3\u670d\u52a1\u5668 jwt \u5b9e\u73b0\u3002<\/li>\n<li>\u4fee\u6539 getuserlogic.go \u5982\u4e0b\uff1a<\/li>\n<\/ol>\n<pre><code>func (l *GetUserLogic) GetUser(req types.GetUserRequest) (*types.GetUserResponse, error) {  return &amp;types.GetUserResponse{Name: \"kim\"}, nil } <\/code><\/pre>\n<ul>\n<li>\u6211\u4eec\u5148\u4e0d\u5e26 JWT Authorization header \u8bf7\u6c42\u5934\u6d4b\u8bd5\u4e0b\uff0c\u8fd4\u56de http status code \u662f 401\uff0c\u7b26\u5408\u9884\u671f\u3002<\/li>\n<\/ul>\n<pre><code>\u279c 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 <\/code><\/pre>\n<ul>\n<li>\u52a0\u4e0a Authorization header \u8bf7\u6c42\u5934\u6d4b\u8bd5\u3002<\/li>\n<\/ul>\n<pre><code>\u279c 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 <\/code><\/pre>\n<p>\u57fa\u4e8e go-zero \u7684 JWT \u8ba4\u8bc1\u5b8c\u6210\uff0c\u5728\u771f\u5b9e\u751f\u4ea7\u73af\u5883\u90e8\u7f72\u65f6\u5019\uff0cAccessSecret, AccessExpire, RefreshAfter \u6839\u636e\u4e1a\u52a1\u573a\u666f\u901a\u8fc7\u914d\u7f6e\u6587\u4ef6\u914d\u7f6e\uff0cRefreshAfter \u662f\u544a\u8bc9\u5ba2\u6237\u7aef\u4ec0\u4e48\u65f6\u5019\u8be5\u5237\u65b0 JWT token \u4e86\uff0c\u4e00\u822c\u90fd\u9700\u8981\u8bbe\u7f6e\u8fc7\u671f\u65f6\u95f4\u524d\u51e0\u5929\u3002<\/p>\n<h2>8. \u9879\u76ee\u5730\u5740<\/h2>\n<p>https:\/\/github.com\/tal-tech\/go-zero<\/p>\n<h2>9. \u5fae\u4fe1\u4ea4\u6d41\u7fa4<\/h2>\n<p><img decoding=\"async\" src=\"http:\/\/4563.org\/wp-content\/uploads\/2020\/09\/20200925_5f6e09cbd4a22.jpg\" alt=\"\u57fa\u4e8e go-zero \u8f7b\u677e\u5b9e\u73b0 JWT \u8ba4\u8bc1\" \/><\/p>\n<\/p><\/div>\n<div> <b>\u5927\u4f6c\u6709\u8a71\u8aaa<\/b> (<span>0<\/span>)        <\/div>\n<div> <\/div>\n<\/p><\/div>\n<\/p><\/div>\n<ul>\n<li>\n","protected":false},"excerpt":{"rendered":"<p>\u57fa\u4e8e go-zero \u8f7b\u677e\u5b9e\u73b0 J&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[],"tags":[],"_links":{"self":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/159773"}],"collection":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=159773"}],"version-history":[{"count":0,"href":"http:\/\/4563.org\/index.php?rest_route=\/wp\/v2\/posts\/159773\/revisions"}],"wp:attachment":[{"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=159773"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=159773"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/4563.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=159773"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}