每週學點 TARS——服務鑑權功能

作者 Eaton

導語

在我們使用微服務架構時,經常會選擇通過 RPC 通信框架方便地實現服務間的調用。但方便的同時也帶來了一些安全隱患,任何用戶都能夠訪問對外公開的接口,可能造成部分敏感數據的泄露,這是我們不希望看到的,怎麼避免呢?這要求我們對訪問的用戶進行鑑別,因此我們需要一個細化到服務的鑑權訪問機制。本文將介紹 TARS 的服務鑑權及其使用方法。

目錄

  • 什麼是鑑權
  • TARS 服務鑑權
    • 服務準備
    • 開啓鑑權
  • 總結

什麼是鑑權

鑑權是指驗證用戶或服務是否具有訪問系統的權利。對於部分公開的接口,我們並不希望所有用戶或服務都能夠訪問,只希望特定的對象能夠訪問,因此我們需要鑑別訪問接口的用戶或服務的身份,確保訪問的對象是我們希望的,保證接口的安全,這就是鑑權。

鑑權一般可分爲用戶鑑權和服務鑑權。

  • 用戶身份鑑權通常依賴於用戶系統,需要在業務代碼中實現,實現方式有很多種,取決於具體的業務需求和使用的用戶系統。

  • 服務鑑權則是對調用方服務的鑑別,確保只有特定的服務或客戶端能夠調用該服務。

TARS 服務鑑權

TARS 提供了一個強大的 RPC 框架,你只需要得到被調用方的 TARS 協議文件,就可以使用TARS框架編碼,請求被調方服務。同時 TARS 框架中還提供了一個細化到服務的鑑權訪問機制,通過賬號密鑰對的形式,使被調服務能夠對調用方進行鑑別。

接下來我們以 TarsCpp爲例,通過一個實例來看看如何在 TARS 中使用服務鑑權。

服務準備

我們需要準備兩個服務,一個是被調服務,一個主調服務。

被調服務 TestServer

首先我們創建一個被調服務,應用名爲 TestApp,服務名爲 TestServerObj 名爲 Test,如下

/usr/local/tars/cpp/script/cmake_tars_server.sh TestApp TestServer Test

生成如下文件

TestServer
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── Test.h
    ├── TestImp.cpp
    ├── TestImp.h
    ├── TestServer.cpp
    ├── TestServer.h
    └── Test.tars

然後修改 Test.tars 文件,定義一個 test 接口,傳入一個字符串 input,返回一個字符串 output

module TestApp
{

interface Test
{
    int test(string input, out string output);
};

};

接着,在 TestImp.cpp 接口實現文件中,添加接口實現,如下

int TestImp::test(const string &input, string &output, tars::TarsCurrentPtr current)
{
    output = input;

    return 0;
}

實現非常簡單,接收到一個字符串,然後直接返回這個字符串。最後,編譯構建服務,並在 TarsWeb 平臺發佈該服務即可。

關於 TARS 服務的創建與部署,參考文檔 TARS 開發入門,這裏不再贅述。

主調服務 HttpServer

爲了便於演示,我們創建一個 HTTP 服務作爲主調服務,這樣我們可以直接通過 HTTP 請求訪問這個服務。服務應用名 TestApp,服務名 HttpServerObj 名爲 Http,命令如下

/usr/local/tars/cpp/script/cmake_http_server.sh TestApp HttpServer Http

生成如下文件

HttpServer
├── build
├── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    ├── HttpImp.cpp
    ├── HttpImp.h
    ├── HttpServer.cpp
    └── HttpServer.h

因爲主調服務要調用被調服務 TestServer 的接口,我們需要將 Test.tars 複製到路徑 src 下。

接着,在 HttpImp.h 中添加一個 TestPrx 類型成員變量 prx_,作爲調用 TestServer 的代理,如下

private:
    TestApp::TestPrx prx_;

然後我們修改 HttpImp.cpp,在 initialize 中初始化 prx_,並添加 doRequest 的實現。

//////////////////////////////////////////////////////
void HttpImp::initialize()
{
    prx_ = Application::getCommunicator()->stringToProxy<TestApp::TestPrx>("TestApp.TestServer.TestObj");
}

...
...

int HttpImp::doRequest(const TC_HttpRequest &req, TC_HttpResponse &rsp)
{
    string msg;
    try
    {   // 調用 test 接口,傳入字符串 HttpServer,msg 獲取 test 返回的字符串
        prx_->test("Hello", msg);
    }
    catch (exception &e)
    {   // 接口調用失敗,捕捉錯誤,傳遞給 msg
        msg = e.what();
    }
    // 設置 HTTP 響應頭
    rsp.setContentType("text/html");
    // 設置 body
    rsp.setResponse(msg.c_str(), msg.size());
    return 0;
}

可以看到 doRequest 函數會嘗試調用 test 接口,並將結果傳遞給 msg。調用失敗則是傳遞錯誤信息給 msg

編譯並在 TarsWeb 平臺上部署這個服務。部署時記得記下部署的端口號,並確保端口可訪問,本例使用 8088 端口。部署後,我們可以使用 curl 命令或者直接使用瀏覽器請求 HttpServer,這時會返回字符串 Hello,如下

$ curl http://192.168.0.121:8088/
Hello

開啓鑑權

TARS 鑑權的使用非常簡單,你不需要修改一行代碼,只需要修改服務的配置。按照下面三個步驟修改即可。

修改被調用方的 endpoint,開啓鑑權機制

在 TarsWeb 平臺,選中需要啓用鑑權的服務,編輯 servant,修改 endpoint,添加 -e 1-e 及其參數表示是否開啓鑑權,默認爲 0 是不開啓的,爲 1 則是開啓。操作如下圖

修改被調用方的配置文件添加賬號密鑰對

在 TarsWeb 平臺,修改服務的私有模板,對 TestApp.TestServer.TestObjAdapter 設置賬號 test 以及密鑰 123456,如下

由於截圖不全,實際私有模板內容如下:

<tars>
  <application>
    <server>
      <TestApp.TestServer.TestObjAdapter>
        accesskey=test
        secretkey=123456
      </TestApp.TestServer.TestObjAdapter>
    </server>
  </application>
</tars>

現在,在 TarsWeb 上重啓 TestServer 服務,然後我們再次請求 HttpServer 服務,結果如下

$ curl http://192.168.0.121:8088/
[ServantProxy::invoke timeout:3000,servant:TestApp.TestServer.TestObj,func:test,adapter:tcp -h 192.168.0.121 -p 29712 -t 3000,reqid:2]

可見服務 HttpServer 調用 TestServer 時超時了,沒有響應。因爲開啓服務鑑權後,請求服務無法匹配賬號和密鑰的話,被調服務會直接關閉連接。

查詢被調服務 TestServer 的日誌,會發現 TestServer 接收到了本次請求,但是認證失敗了,因此直接關閉了此連接。

2020-11-10 19:09:35|140215793313664|DEBUG|[TARS]accept [192.168.0.121:38279] [17] incomming
2020-11-10 19:09:35|140215247173376|ERROR|[TARS]authProcess failed with new state [AUTH_WRONG_AK]
2020-11-10 19:09:35|140215247173376|DEBUG|[TARS]send [192.168.0.121:38279] close connection by user.

修改主調方的配置文件添加賬號密鑰

要讓主調服務 HttpServer 能夠調用開啓了鑑權的 TestServer 服務,我們也要在 HttpServer 中配置相同賬號和密鑰。

配置方式同樣是在私有模板中配置,如圖,配置調用 TestApp.TestServer.TestObj 的賬號 test 和密鑰 123456

由於截圖不全,實際私有模板內容如下:

<tars>
  <application>
    <client>
      <TestApp.TestServer.TestObj>
        accesskey=test
        secretkey=123456
      </TestApp.TestServer.TestObj>
    </client>
  </application>
</tars>

現在,在 TarsWeb 重啓 HttpServer 服務,我們再次發起請求,結果如下

$ curl http://192.168.0.121:8088/
Hello

返回 Hello,說明本次調用鑑權成功。

進階:主調方需要調用多個開啓鑑權的被調服務時,只需在上述模板文件的 client 域中,繼續以相同的方式添加被調服務,並添加屬性 accesskeysecretkey 即可,如下

<tars>
  <application>
    <client>
      <TestApp.TestServer.TestObj>
        accesskey=test
        secretkey=123456
      </TestApp.TestServer.TestObj>
      <TestApp.AnotherServer.HelloObj>
        accesskey=hello
        secretkey=654321
      </TestApp.AnotherServer.HelloObj>
    </client>
  </application>
</tars>

總結

本文介紹了 TARS 框架中的服務鑑權功能以及如何使用。從文中實例可以看出,服務鑑權完全與業務代碼無關,在框架層面實現。通過 TARS 服務鑑權,能夠實現服務間身份的鑑別,從而確保一些敏感接口的安全,避免被濫用。

TARS 可以在考慮到易用性和高性能的同時快速構建系統並自動生成代碼,幫助開發人員和企業以微服務的方式快速構建自己穩定可靠的分佈式應用,從而令開發人員只關注業務邏輯,提高運營效率。多語言、敏捷研發、高可用和高效運營的特性使 TARS 成爲企業級產品。

TARS微服務助您數字化轉型,歡迎訪問:

TARS官網:https://TarsCloud.org

TARS源碼:https://github.com/TarsCloud

Linux基金會官方微服務免費課程:https://www.edx.org/course/building-microservice-platforms-with-tars

獲取《TARS官方培訓電子書》:https://wj.qq.com/s2/6570357/3adb/

或掃碼獲取:

QR

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章