Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Dubbo调用鉴权认证方案 #5461

Closed
CodingSinger opened this issue Dec 11, 2019 · 8 comments
Closed

Dubbo调用鉴权认证方案 #5461

CodingSinger opened this issue Dec 11, 2019 · 8 comments
Milestone

Comments

@CodingSinger
Copy link
Member

CodingSinger commented Dec 11, 2019

基本需求:

  • 一些敏感服务的provider,只允许经过授权的consumer应用发起的调用,不允许匿名调用。

方案设计:

  1. 基于AK/SK,即Access Key ID和Secret Access Key。
  2. AK/SK需要应用启动时向鉴权服务拉取,定期更新。为保证安全,用HTTPS通信。
  3. 签名和验签基于filter。

dubbo-auth.png

细节说明

  1. 签名过程,调用方可选择签名策略,选择根据调用元信息签名(方法信息、接口信息)和混合参数签名方法。

  2. 验签过程:provider收到调用请求时,根据AK查询缓存的SK(如果没有对应的AK,则立刻同步一次鉴权服务),并用同样方法计算signature,检查signature是否相同, 通过则执行调用,否则抛出异常。

鉴权服务接口设计

鉴权服务是Dubbo的外部服务,进行统一管理AK/SK,并为Dubbo应用提供AK/SK下发。

接口地址https://ip:80/secrets/{appName}

请求方式: GET

返回数据格式: JSON

返回数据定义:

 {
        "cumsomer":[  // 申请到访问其他服务的AK/SK对
            {
                "accessKey":"", // AK
                "secretKey":"", // SK
                "consumerSide":"", // 消费端appname
                "providerSide":"", // 服务端appname
                "timestamp":"",   // 有效期
                "options":""     // 其他信息
            }
        ],
        "provider":[   // 自己提供出去承认其他应用访问的AK/SK对
            {
                "accessKey":"", // AK
                "secretKey":"", // SK
                "consumerSide":"", // 消费端appname
                "providerSide":"", // 服务端appname
                "timestamp":"",   // 有效期
                "options":""     // 其他信息
            } 
        ]
        
    }
@chickenlj chickenlj pinned this issue Dec 11, 2019
@chickenlj chickenlj unpinned this issue Dec 11, 2019
@chickenlj chickenlj pinned this issue Dec 11, 2019
@w6et
Copy link

w6et commented Dec 14, 2019

提一个简单的方案,全局或者每个provider,可以指定allow_apps\deny_apps(block_apps)
1)如果配了allow_apps,那就按白名单玩,必须白名单里才能调用
2)如果配了deny_apps,那就按黑名单玩,非黑名单的都能调用
这样:
1)不用考虑证书失效or过期or置换情况;
2)基本够用:限制到app层面,一般够用了(因为是内部调用,假设上线也是经过check的,流程上是可以保障的)

备注一下:是控制app背后的ip访问限制

@CodingSinger
Copy link
Member Author

@amwei 嗯 你这个确实比较简单,实现也容易很多,基本靠一个provider端的filter会实现了,但是后续对于黑白名单的增加还得重启。上面说的方案引入了一个额外的系统,确实复杂度会提高,但是在安全性和扩展性方面都会有很大的改善,目前我们也在权衡。

@laddcn
Copy link
Contributor

laddcn commented Dec 20, 2019

鉴权服务和各个微服务之间是可信内网通信吗?如果外网负责环境的话是不是还要考虑下HTTPS和TLS的中间人攻击问题,AK/SK下发和更新过程中可能会被中间人截获。

@laddcn
Copy link
Contributor

laddcn commented Dec 20, 2019

当然这样考虑问题就会复杂了

@chickenlj chickenlj added this to the 2.7.6 milestone Dec 30, 2019
@nisiyong
Copy link
Contributor

nisiyong commented Jan 6, 2020

@CodingSinger

我们最近也在做服务身份认证的方案,你这种实现是中心化的实现。鉴权服务需要高可用,如果鉴权服务宕了,你们是如何考虑的?

对于服务黑白名单,我们考虑直接用sentinel来做即可,这是服务鉴权。在这之前做好身份认证即可,保证调用方不是伪造的。

@nisiyong
Copy link
Contributor

nisiyong commented Jan 6, 2020

这里也贴下我们的方案吧,一起探讨下。

基本流程

image

如上图,流程如下:

  1. 为每个应用生成一对公私钥,私钥给应用独立配置,所有公钥集中统一管理(我们采用配置中心公共配置),所有应用都能获取到所有公钥
  2. 服务A使用自己的私钥,根据应用名和时间等,用私钥对app和timestamp进行签名生成token(可采用JWT规范)
  3. 在每次调用时将token通过上下文透传给服务B
  4. 服务B接受到请求后,判断token是否合法(通过该应用的公钥验证token),否则拒绝请求
  5. 认证信息校验合法后,进行业务处理并响应

性能优化

由于token的生成和校验用了非对称加密算法,在性能上有一定的影响,为了解决该问题,我们引入“预生成”和“预校验”,结合内存缓存一起使用。

image

“预生成”逻辑:(假设每小时产生一个新的token)

  1. 在0h时,token-1可以在启动起同步生成初始化,作为上下文的token字段的值;并异步生成token-2,作为上下文next_token字段的值
  2. 在1h时,token-2上下文的token字段的值;并异步生成token-3,作为上下文next_token字段的值
  3. 在2h时,token-3上下文的token字段的值;并异步生成token-4,作为上下文next_token字段的值
    ...

“预校验”逻辑:(假设token的缓存失效时间为客户端弃用半小时后)

  1. 在0h时,接收到token-1并同步校验,校验成功加入内存缓存;并异步校验token-2,校验成功加入内存缓存
  2. 在1h时,接收到token-2可直接用内存缓存比较,无需计算;并异步校验token-3,校验成功加入内存缓存
  3. 在2h时,接收到token-3可直接用内存缓存比较,无需计算;并异步校验token-4,校验成功加入内存缓存
    ...

通过以上两种方式结合:

  • 可以避免非对称加密算法在业务线程中执行
  • 可以解决token平滑切换,解决毛刺问题

总结

该方案是基于去中心化设计的,而且只解决身份认证问题,证明调用方A就是真的A,而不是伪造的A。至于A能否调用B,或能调用哪个接口,我们考虑直接用Sentinel的黑白名单来做补充。

@liushuaifei
Copy link

liushuaifei commented Oct 11, 2021

定期更新可以改为握手时获取加监听变化,利用rpc服务发现的长链接信道。

@phenix229
Copy link

您好,鉴权认证的方案在dubbo-2.7.6中,是否可以使用?

@phenix229 phenix229 mentioned this issue May 18, 2022
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants