本文介绍go micro中的api拜访权限管制,这里仅仅介绍外部服务间的相互调用鉴权(jwt),不是针对用户零碎的粗疏rbac模式。
指标:
- 外部服务间调用应在header上带上jwt token,否则返回谬误提示信息
有2种形式
- 在每个服务上各自鉴权
- 在网关上鉴权,各服务只需注册一个wrapper查看header中jwt信息鉴权。这样做有个前提,所有服务需放到同一个网络内,走对立的服务注册核心,这里次要介绍这种形式。
先创立一个myauth的服务,对外提供2个接口
- GetJwt() 返回jwt token,能够用用户名明码或其余形式验证,依据具体业务灵便决定即可,这里示例采纳服务名和密钥方
- InspectJwt() 验证jwt token是否无效
- 自定义一个网关,通过插件形式wrapper指定一个鉴权函数,除了第3步中的2个接口外,其余都须要header中有jwt的token
- 其余业务只须要注册一个wrapper查看header中jwt信息鉴权
业务调用步骤
- 调用GetJwt()获取jwt token
- 调用其余接口时,在header退出jwt token
首先创立一个api我的项目
micro new --type=api myauth
GetJwt()、InspectJwt()
相干代码
// Myauth.Call is called by the API as /myauth/call with post body {"name": "foo"}func (e *Myauth) GetJwt(ctx context.Context, req *api.Request, rsp *api.Response) error { log.Info("Received Myauth.GetJwt request") getmap := req.GetGet() log.Info("Received getmap %+v\n", getmap) postmap := req.GetPost() log.Info("Received postmap %+v\n", postmap) // 外部服务调用底层service,通过jwt验证 // 定义服务名和key,通过这2个参数获取jwt access token // serviceName := "order" // serviceKey := "123456" // 比照serviceName\serviceKey 也能够是用户名明码等,这里的示例为了不便硬编码在代码中 // 理论我的项目中应该从数据库或文件读取 serviceName := extractValue(postmap["service"]) serviceKey := extractValue(postmap["key"]) log.Info("serviceName %+v\n", serviceName, serviceKey) if serviceName != "order" || serviceKey != "123456" { Rsp(rsp, 403, "服务名称或key谬误", nil) return nil } //生成jwt // expireTime := time.Now().Add(time.Hour * 24 * 3).Unix() expireTime := time.Now().Add(time.Second * 60 * 60).Unix() token := &token.Token{} token.Init([]byte("key123456")) //理论我的项目需从数据库或文件读取 jwtstring, err := token.Encode("auth jwt", serviceName, expireTime) if err != nil { Rsp(rsp, 403, "jwt 生成谬误", nil) return nil } msg := make(map[string]interface{}) msg["jwt"] = jwtstring Rsp(rsp, 200, "ok", msg) return nil}// 验证jwtfunc (e *Myauth) InspectJwt(ctx context.Context, req *api.Request, rsp *api.Response) error { log.Info("Received Myauth.InspectJwt request") // getmap := req.GetGet() // log.Info("Received getmap %+v\n", getmap) postmap := req.GetPost() // log.Info("Received postmap %+v\n", postmap) jwtString := extractValue(postmap["jwt"]) log.Info("jwtString %+v\n", jwtString) if len(jwtString) == 0 { Rsp(rsp, 403, "jwt参数谬误", nil) return nil } //解析jwt token := &token.Token{} token.Init([]byte("key123456")) info, err := token.Decode(jwtString) if err != nil { Rsp(rsp, 403, "jwt 解析谬误", nil) //过期或jwt有问题 return nil } t := make(map[string]interface{}) t["data"] = info Rsp(rsp, 200, "ok", t) return nil}// 返回funcfunc Rsp(rsp *api.Response, code int, err string, msg map[string]interface{}) error { if msg == nil { msg = make(map[string]interface{}) } r := &rspMsg{ Code: code, Err: err, Msg: msg, } b, err2 := json.Marshal(r) if err2 != nil { log.Info("json.Marshal err", err2) } rsp.StatusCode = int32(code) rsp.Body = string(b) return nil}
自定义micro网关代码
package mainimport ( "net/http" "myauth/lib/token" log "github.com/micro/go-micro/v2/logger" "github.com/micro/micro/v2/cmd" "github.com/micro/micro/v2/plugin")func main() { tk := &token.Token{} tk.Init([]byte("key123456")) plugin.Register(plugin.NewPlugin( plugin.WithName("auth"), plugin.WithHandler( JWTAuthWrapper(tk), ), )) cmd.Init()}func JWTAuthWrapper(t *token.Token) plugin.Handler { return func(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Info("===========", r.URL.Path) //不须要登录的url地址 strings.HasPrefix(r.URL.Path, "/hello") || if r.URL.Path == "/myauth/Myauth/GetJwt" || r.URL.Path == "/myauth/Myauth/InspectJwt" { h.ServeHTTP(w, r) return } // tokenstr := r.Header.Get("Authorization")//当初不能够用Authorization,须要用Bearer tokenstr := r.Header.Get("Bearer") log.Info("tokenstr", tokenstr) userFromToken, e := t.Decode(tokenstr) log.Info("userFromToken", userFromToken) if e != nil { _, _ = w.Write([]byte("unauthorized")) return } // r.Header.Set("X-Example-Username", userFromToken.UserName) h.ServeHTTP(w, r) return }) }}
示例代码见https://github.com/wulinlw/mi...
参考
go-micro网关鉴权之jwt
https://www.jianshu.com/p/426...
【go语言微服务实际】#5-go-micro实现JWT认证
https://juejin.im/post/5e6123...
https://github.com/Allenxuxu/...