Dubbo介面授權

貝途發表於2017-08-15
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");
複製程式碼
許可權的設計就比較簡單了:
Dubbo介面授權許可權粒度可以根據自己的需要設計。

還可以實現更復雜的驗證,比如加上時間戳、簽名。但是設定這些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介面授權機制就完成了。


相關文章