使用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:provider filter="自定义filter的名称"/>
复制代码
consumer通过attachment把appId传递给provider,那么provider就知道是谁发起调用了,在consumer可以这样设置:
RpcContext.getContext().setAttachment("appId", "someAppId");
复制代码
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接口授权机制就完成了。