dubbo-go 可信 RPC 调用实现

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
注册配置 MSE Nacos/ZooKeeper,118元/月
性能测试 PTS,5000VUM额度
简介:

Apache Dubbo/Dubbo-Go 作为阿里巴巴开源的一款服务治理框架,因其适应 Java/Go 开发者面向接口的编程习惯、完全透明的调用方式、优越的性能以及强大的扩展性等优点,在国内使用非常广泛。除此之外,Dubbo 开源版本原生集成了很多开箱即用的服务治理功能,包括链路追踪,路由、负载均衡、服务注册发现、监控、认证等。

本文将讲解如何在 Dubbo/Dubbo-Go 中实现灵活、安全和高效的身份验证和授权方案。

定义可信

何为可信?可信的定义很广泛,依场景不同有不同的定义。在微服务架构中,每个服务都是无状态的,多个服务之间不可信,为了实现服务间更好地隔离,服务间应进行认证和鉴权。

如支付之类的业务场景,安全性敏感的服务会有限制匿名系统调用的需求,其他业务在接入该类敏感业务之前,需要通过审批方可正常调用,这就需要对这类敏感服务进行权限管控。尽管 Dubbo 开源版本中支持 Token 方式的鉴权实现,但是该实现方式总体来说安全性并不高,并且无法满足我们需要动态下发以及变更的灵活性需求。

针对于此,我们内部着重从巩固安全性和拓展灵活性层面重新设计了一套 Dubbo/Dubbo-Go 的服务间调用的鉴权认证功能。本文我们将主要从实现层面讲解其大致实现思路。

可信方案

总体而言,鉴权认证主要讨论以下两个问题:

1、身份认证:指验证应用的身份,每个应用在其生命周期内只有唯一身份,无法变更和伪造。
2、权限鉴定:根据身份信息鉴定权限是否满足调用。权限粒度可以进行控制。

我们通过 Access Key ID/Secret Access Key (后文简称为 AK/SK) 信息标识应用和应用之间的身份关系。例如上游 应用A 依赖下游 服务B 和 C,则 A 对 B 和 C 分别有一套 AK/SK,其相互独立没有任何关系,就算 A服务 的 AK/SK 信息泄漏,也无法通过该 AK/SK 信息调用其他的服务。

在权限鉴定方面也借鉴了公有云开放 API 常用的 AK/SK 签名机制。在请求过程中使用 SK 签名生成 SigningKey,并通过 Dubbo 的 attachment 机制将额外的元数据信息以及 SigningKey 传输到服务端,交由服务端计算和验签,验签通过方能正常处理和响应。

签名过程主要通过如下三个方式进行加强 SigningKey 的可靠性和安全性。

1、验证请求者的身份,签名会通过对应应用的SK作为加密密钥对请求元数据(以及参数)进行加密,保证签名的唯一性和不可伪造性。
2、支持对参数进行计算签名,防止非法篡改,若请求参数在传输过程中遭到非法篡改,则收到请求后服务端验签匹配将失败,身份校验无法通过,从而防止请求参数被篡改。考虑到签名以及验签过程中加入请求参数的计算可能会影响性能,这个过程是可选的。
3、防止重放攻击,每一次请求生成的SigningKey都具有指定的有效时间,如请求被截获,该请求无法在有效时间外进行调用,一定程度避免了重放攻击。

同时为了去掉明文配置,防止 AK/SK 信息泄漏,我们通过鉴权系统分发和管理所有 AK/SK 信息。通过对接内部审批流程,达到流程化和规范化,需要鉴权的应用会通过启动获取的方式拉当前应用分发出去或者是已被授权的 AK/SK 信息。这种方式也带来了另一种好处,新增、吊销以及更新权限信息也无需重启应用。

可信流程

结合上面的这些需求和方案,整个接入和鉴权流程图如下所示:

lALPD3W5LIKUvWXNAbfNAmQ_612_439_png_720x720q90g

整体流程如下:

1、使用该功能的应用需要提前申请对应的证书,并向提供服务的应用提交申请访问工单,由双方负责人审批通过后,请求鉴权服务中心自动生成键值对。

2、开启鉴权认证的服务在应用启动之后,会运行一个后台线程,长轮询远鉴权服务中心,查询是否有新增权限变动信息,如果有则进行全量/增量的拉取。
3、上游应用在请求需要鉴权的服务时,会通过 SK 作为签名算法的 key,对本次请求的元数据信息甚至是参数信息进行计算得到签名,通过 Dubbo 协议 Attachment 字段传送到对端,除此之外还有请求时间戳、AK 信息等信息。
4、下游应用在处理鉴权服务时会对请求验签,验签通过则继续处理请求,否则直接返回异常。

其中需要说明的是第三步,使用鉴权服务的应用和鉴权服务中心的交互需通过 HTTPS 的双向认证,并在 TLS 信道上进行数据交互,保证 AK/SK 信息传输的安全性。

该方案目前已经有 Java/Go 实现,均已合并到 dubbo/dubbo-go。除了默认的 Hmac 签名算法实现之外,我们将签名和认证方法进行抽象,以 dubbo-go中的实现为例:
// Authenticator
type Authenticator interface {

// Sign
// give a sign to request
Sign(protocol.Invocation, *common.URL) error
// Authenticate
// verify the signature of the request is valid or not
Authenticate(protocol.Invocation, *common.URL) error

}

使用者可通过 SPI 机制定制签名和认证方式,以及适配公司内部基础设施的密钥服务下发 AK/SK。

示例

以 Helloworld 示例 中的代码接入当前社区版本中的默认鉴权认证功能实现为例:

Helloworld 示例:

https://github.com/apache/dubbo-samples/tree/master/golang/helloworld/dubbo

在无需改变代码的情况下,只需要在配置上增加额外的相关鉴权配置即可,dubbo-go 服务端配置示例如下:

services:
  "UserProvider":
    # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册
    registry: "hangzhouzk"
    protocol : "dubbo"
    # 相当于dubbo.xml中的interface
    interface : "com.ikurento.user.UserProvider"
    loadbalance: "random"
    # 本服务开启auth
    auth: "true"  
    # 启用auth filter,对请求进行验签
    filter: "auth"
    # 默认实现通过配置文件配置AK、SK
    params:
      .accessKeyId: "SYD8-23DF"
      .secretAccessKey: "BSDY-FDF1"
    warmup: "100"
    cluster: "failover"
    methods:
      - name: "GetUser"
        retries: 1
        loadbalance: "random"

dubbo-go 客户端配置示例如下:

references:
  "UserProvider":
    # 可以指定多个registry,使用逗号隔开;不指定默认向所有注册中心注册
    registry: "hangzhouzk"
    protocol: "dubbo"
    interface: "com.ikurento.user.UserProvider"
    cluster: "failover"
    # 本服务开启sign filter,需要签名
    filter: "sign"
    # 默认实现通过配置文件配置AK、SK
    params:
      .accessKeyId: "SYD8-23DF"
      .secretAccessKey: "BSDY-FDF1"
    methods:
      - name: "GetUser"
        retries: 3

可以看到,dubbo-go 接入鉴权认证的功能也十分简单。需要补充说明的是,配置文件文件中 ak/sk 都加了特殊前缀 ".",是为了说明该字段是敏感信息,不能在发起网络请求时传输出去,相关代码可参阅 dubbo-go-pr-509。

dubbo-go-pr-509:
https://github.com/apache/dubbo-go/pull/509

总结

Apache Dubbo 作为一款老而弥新的服务治理框架,无论是其自身还是其生态都还在飞速进化中。本文描述的最新实现的可信服务调用,是为了避免敏感接口被匿名用户调用而在 SDK 层面提供的额外保障,在 RPC 层面保障安全性。

dubbo-go 作为 Dubbo 生态中发展最快的成员,目前基本上保持与 Dubbo 齐头并进的态势。dubbo-go 社区钉钉群号为 23331795, 欢迎你的加入。

作者信息:郑泽超,Apache Dubbo/Dubbo-Go committer,GithubID: CodingSinger,目前就职于上海爱奇艺科技有限公司,Java/Golang 开发工程师。

相关文章
|
7月前
|
Dubbo Java 应用服务中间件
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
微服务学习 | Springboot整合Dubbo+Nacos实现RPC调用
|
7月前
|
负载均衡 Dubbo Java
Dubbo 3.x:探索阿里巴巴的开源RPC框架新技术
随着微服务架构的兴起,远程过程调用(RPC)框架成为了关键组件。Dubbo,作为阿里巴巴的开源RPC框架,已经演进到了3.x版本,带来了许多新特性和技术改进。本文将探讨Dubbo 3.x中的一些最新技术,包括服务注册与发现、负载均衡、服务治理等,并通过代码示例展示其使用方式。
372 9
|
7月前
|
JSON Go 数据格式
从1开始,扩展Go语言后端业务系统的RPC功能
从1开始,扩展Go语言后端业务系统的RPC功能
91 0
|
7月前
|
Dubbo Cloud Native 网络协议
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
【Dubbo3技术专题】「服务架构体系」第一章之Dubbo3新特性要点之RPC协议分析介绍
96 1
|
中间件 Go 数据处理
Go语言学习 - RPC篇:gRPC-Gateway定制mux选项
通过上一讲,我们对gRPC的拦截器有了一定的认识,也能定制出很多通用的中间件。 但在大部分的业务系统中,我们面向的还是HTTP协议。那么,今天我们就从gRPC-Gateway的mux选项出发,一起来看看一些很实用的特性。
235 0
|
编解码 中间件 Go
Go语言学习 - RPC篇:gRPC拦截器剖析
我们在前几讲提到过,优秀的RPC框架都提供了`middleware`的能力,可以减少很多重复代码的编写。在gRPC-Gateway的方案里,包括了两块中间件的能力: 1. gRPC中的`ServerOption`,是所有gRPC+HTTP都会被处理 2. gRPC-Gateway中的`ServeMuxOption`,只有HTTP协议会被处理 今天,我们先关注共同部分的`ServerOption`,它提供的能力最为全面,让我们一起了解下。
90 0
|
存储 JSON Go
Go语言学习 - RPC篇:深入gRPC-Gateway-探索常用数据类型
今天,我们先迈出第一步:探索RPC服务中的数据类型。掌握常见的数据类型,灵活地运用到接口设计中,能帮助我们快速地提供优雅的接口类服务。
90 0
|
3月前
|
XML 负载均衡 监控
分布式-dubbo-简易版的RPC框架
分布式-dubbo-简易版的RPC框架
|
7月前
|
Dubbo Java 应用服务中间件
Spring Boot整合Dubbo+Zookeeper实现RPC调用
Spring Boot整合Dubbo+Zookeeper实现RPC调用 技术栈说明 Dubbo:Dubbo作为RPC框架,能在多个服务之间实现远程服务的调用。比如有两个独立的微服务A和B,A服务想要调用B服务时,因为两者不在同个内存空间中,不能直接调用,所以可以通过Dubbo实现这点。 功能和Spring Cloud的Feign相同,两者都是应用于微服务架构的远程调用框架 Zookeeper:作为注册中心去管理Dubbo服务,这点和Eureka、Nacos相同。 概述 通过一个示例说明Dubbo+Zookeeper在Spring Boot中的应用。 现有两个服务provider和con
184 4
|
7月前
|
Java fastjson 数据安全/隐私保护
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
【Dubbo3技术专题】「云原生微服务开发实战」 一同探索和分析研究RPC服务的底层原理和实现
156 0