package micro import ( "context" "dashoo.cn/micro_libary/gtoken" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/text/gstr" "github.com/rcrowley/go-metrics" "github.com/rpcxio/rpcx-consul/serverplugin" "github.com/smallnest/rpcx/protocol" "github.com/smallnest/rpcx/server" "github.com/smallnest/rpcx/share" "strings" "time" ) const Tenant = "Tenant" func CreateAndInitService(basePath string) *server.Server { var ctx = gctx.New() bindAddr, _ := g.Config().Get(ctx, "setting.bind-addr") registryType, _ := g.Config().Get(ctx, "setting.registry-type") registryAddr, _ := g.Config().Get(ctx, "setting.registry-addr") s := server.NewServer() g.Log().Infof(context.Background(), "服务启动, BindName: %v, BindAddr: %s", basePath, bindAddr.String()) if registryType.String() == "consul" { addConsulRegistryPlugin(ctx, s, basePath, bindAddr.String(), registryAddr.String()) } return s } func addConsulRegistryPlugin(ctx context.Context, s *server.Server, basePath, srvAddr, consulAddr string) { r := &serverplugin.ConsulRegisterPlugin{ ServiceAddress: "tcp@" + srvAddr, ConsulServers: []string{consulAddr}, BasePath: basePath, Metrics: metrics.NewRegistry(), UpdateInterval: time.Minute, } err := r.Start() if err != nil { g.Log().Fatal(ctx, err) } g.Log().Infof(ctx, "注册到Consul: %v, basePath: %v, MicorSrv: %v", consulAddr, basePath, srvAddr) s.Plugins.Add(r) } // HandleAuth 处理身份验证 func HandleAuth(ctx context.Context, req *protocol.Message, token string, authExcludePaths []string) error { tenant := getTenant(req) g.Log().Infof(ctx, " ServicePath: %s, ServiceMethod: %s,Tenant:%s", req.ServicePath, req.ServiceMethod, tenant) reqPath := "/" + req.ServicePath + "/" + req.ServiceMethod if authPath(reqPath, authExcludePaths) { req.Metadata["authExclude"] = "false" var rsp gtoken.Resp notAuthSrv := ctx.Value("NotAuthSrv") if notAuthSrv != nil && notAuthSrv.(bool) { rsp = gtoken.GFToken.ValidToken(ctx, token) } else { ctx = context.WithValue(ctx, share.ReqMetaDataKey, map[string]string{"tenant": tenant}) rsp = validToken(ctx, token) } if rsp.Code != 0 && rsp.Code != 200 { return gerror.New("Token 认证失败!") } if req.Metadata != nil { req.Metadata["userInfo"] = rsp.DataString() } return nil } return nil } // 判断路径是否需要进行认证拦截 // return true 需要认证 func authPath(urlPath string, authExcludePaths []string) bool { // 去除后斜杠 if strings.HasSuffix(urlPath, "/") { urlPath = gstr.SubStr(urlPath, 0, len(urlPath)-1) } // 排除路径处理,到这里nextFlag为true for _, excludePath := range authExcludePaths { tmpPath := excludePath // 前缀匹配 if strings.HasSuffix(tmpPath, "/*") { tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-2) if gstr.HasPrefix(urlPath, tmpPath) { // 前缀匹配不拦截 return false } } else { // 全路径匹配 if strings.HasSuffix(tmpPath, "/") { tmpPath = gstr.SubStr(tmpPath, 0, len(tmpPath)-1) } if urlPath == tmpPath { // 全路径匹配不拦截 return false } } } return true } // 验证token func validToken(ctx context.Context, token string) gtoken.Resp { grsp := gtoken.Resp{} if token == "" { grsp.Code = 401 grsp.Msg = "valid token empty" return grsp } authService := InitMicroSrvClient(ctx, "Auth", "micro_srv.auth") defer authService.Close() rsp := >oken.Resp{} err := authService.Call(ctx, "ValidToken", token, rsp) if err != nil { g.Log().Error(ctx, err) grsp.Code = 401 return grsp } grsp.Code = int(rsp.Code) grsp.Msg = rsp.Msg grsp.Data = rsp.Data return grsp } func getTenant(msg *protocol.Message) string { var tenant string if msg.Metadata != nil { tenant = msg.Metadata[Tenant] } return tenant }