使用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介面授權機制就完成了。