作者 Eaton
導語
在我們使用微服務架構時,經常會選擇通過 RPC 通信框架方便地實現服務間的調用。但方便的同時也帶來了一些安全隱患,任何用戶都能夠訪問對外公開的接口,可能造成部分敏感數據的泄露,這是我們不希望看到的,怎麼避免呢?這要求我們對訪問的用戶進行鑑別,因此我們需要一個細化到服務的鑑權訪問機制。本文將介紹 TARS 的服務鑑權及其使用方法。
目錄
- 什麼是鑑權
- TARS 服務鑑權
- 服務準備
- 開啓鑑權
- 總結
什麼是鑑權
鑑權是指驗證用戶或服務是否具有訪問系統的權利。對於部分公開的接口,我們並不希望所有用戶或服務都能夠訪問,只希望特定的對象能夠訪問,因此我們需要鑑別訪問接口的用戶或服務的身份,確保訪問的對象是我們希望的,保證接口的安全,這就是鑑權。
鑑權一般可分爲用戶鑑權和服務鑑權。
-
用戶身份鑑權通常依賴於用戶系統,需要在業務代碼中實現,實現方式有很多種,取決於具體的業務需求和使用的用戶系統。
-
服務鑑權則是對調用方服務的鑑別,確保只有特定的服務或客戶端能夠調用該服務。
TARS 服務鑑權
TARS 提供了一個強大的 RPC 框架,你只需要得到被調用方的 TARS 協議文件,就可以使用TARS框架編碼,請求被調方服務。同時 TARS 框架中還提供了一個細化到服務的鑑權訪問機制,通過賬號密鑰對的形式,使被調服務能夠對調用方進行鑑別。
接下來我們以 TarsCpp爲例,通過一個實例來看看如何在 TARS 中使用服務鑑權。
服務準備
我們需要準備兩個服務,一個是被調服務,一個主調服務。
被調服務 TestServer
首先我們創建一個被調服務,應用名爲 TestApp
,服務名爲 TestServer
,Obj
名爲 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
,服務名 HttpServer
,Obj
名爲 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
域中,繼續以相同的方式添加被調服務,並添加屬性accesskey
和secretkey
即可,如下
<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/
或掃碼獲取: