Bootstrap

Dubbo接口授权

Dubbo是阿里巴巴开源的一个分布式服务框架,在我们 贝聊内部,广泛地使用了这个框架。

使用Dubbo可以很方便地进行远程服务调用,在同一个注册中心,业务系统可以随意调用其他服务。但是有时候我们希望某些接口只有符合条件的用户才能调用,其他人不能随意调用。

Dubbo本身没有接口的授权机制,我们决定为Dubbo加上这个机制。大致是这样:

授权应该满足不同的粒度:

  • 所有接口
  • 部分接口
  • 某个接口
同时,如果授权服务不可用,不应该影响接口的访问。


在Dubbo中,provider可以通过实现com.alibaba.dubbo.rpc.Filter对接口的调用进行处理:

/**
 * 处理Dubbo接口授权
 */
public class AuthorizationFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        if (授权通过) {
            return invoker.invoke(invocation);
        }
        else {
            // TODO 错误处理
        }
    }
}
复制代码
Dubbo配置:
<dubbo:provider filter="自定义filter的名称"/>
复制代码
那么,如何知道调用者是谁?我们可以给每个系统分配一个ID,比如叫appId。

consumer通过attachment把appId传递给provider,那么provider就知道是谁发起调用了,在consumer可以这样设置:
RpcContext.getContext().setAttachment("appId", "someAppId");
复制代码
在provider读取appId:
String appId = invocation.getAttachment("appId");
复制代码
权限的设计就比较简单了:
权限粒度可以根据自己的需要设计。

还可以实现更复杂的验证,比如加上时间戳、签名。但是设置这些attachment对于consumer是比较麻烦的,每次调用都要设置,如果将来规则变化,就更麻烦了。

于是我们再写一个filter处理consumer的attachment:
public class ConsumerContextFilter implements Filter {
    /*
     * TODO 通过读取配置或注入appId
     */
    private String appId;
    
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        // 设置appId
        RpcContext.getContext().setAttachment("appId", appId);
        
        // 执行接口
        return invoker.invoke(invocation);
    }
}
复制代码

这样 consumer 通过配置 filter 的方式就完成了授权参数的设置,所有调用 provider 的代码不需要做任何修改。

至此,一个简单的Dubbo接口授权机制就完成了。


;