實時搜尋:如何用Javascript客戶端保證安全

KingDou發表於2014-03-28

實時性是我們的根本,所以當我們建立Algolia的時候,首先考慮的是建立一個可以在毫秒內返回相關查詢結果的搜尋後端。但是,後端部分只是影響實時性公式的一部分因素。事實上,使用者所能察覺到的反應時間是從他們敲擊鍵盤到顯示結果的時間。所以非常快速的搜尋後端只是把解決該公式的問題就落在了處理忘了延遲上了。我們通過下面兩步來解決這個問題:

首先:我們在三個不同的地方都有資料中心,這些資料中心可以使我們在100ms內回答來自北美、歐洲和亞洲的查詢。

其次:為了減少這種使用者感知時延,使用者的查詢應該直接通過使用者的瀏覽器或者移動手機傳送到我們的伺服器,同時,避免中間媒介比如你自己的伺服器。這就是我們為網站提供javascript客戶端,為手機應用提供Objc/Android/C#客戶端的原因。

JavaScript的安全挑戰

使用這個客戶端意味著你需要在你的javascript(或者手機APP)中包括API KEY。使用這種方式的安全問題是任何人可以簡單地通過檢視頁面的原始碼來檢視使用者的API金鑰,潛在地允許這個使用者修改網站/移動應用程式。為了解決這個問題,我開始提供只允許查詢的API KEY來保護你的索引免受未授權的修改。

限制抓取你資料的能力:你可能不想人通過重複的查詢獲取你所有的資料。簡單的解決方法是限制在指定時間內使用者可以呼叫API的次數。我們通過限制每個IP的比率實現了。然而,這種方法是不能接受的如果很多的使用者都是受全域性防火牆的保護。這種情況在企業使用者中是很有可能發生的。

安全的訪問控制:你可能需要限制使用者對特定內容的查詢。例如,你可能有些重要使用者應該比其他使用者可以訪問更多的內容。做這件事的簡單辦法就是使用過濾。問題是在javaScript中設定簡單的過濾,人們可以弄明白如何修改這些過濾條件,訪問他們不應該訪問的內容。

我們是如何解決這些問題:

現在,大多數的網站和應用都需要使用者建立使用者並且登入以獲得個人的資訊(考慮下CRM應用、Facebook和NetFix)。我們決定使用這些使用者的ID來建立簽名的API金鑰來解決這個問題。比如說你只有查詢許可權的API金鑰,
想要在兩組人內容上對某一個指定的使用者(id=42)使用過濾。

你可以在後端生成一個安全的由三個元素組成的雜湊定義的API金鑰:

比如,如果你是使用Rails,那麼後端的程式碼應該是:

你可以使用安全的API金鑰和相關資訊初始化你的JavaScript程式碼。

使用使用者標識(通過設定使用者訪問券定義)而不是使用IP地址來進行比率限制,並且這個安全過濾(通過設定安全標籤定義)被自動的應用到查詢。

實際上,如果使用者想要超越他的許可權,她需要修改她的安全標籤並且弄明白新的雜湊。

我們的後端通過你所有可能的查詢索引的API金鑰和查詢中定義的安全標和使用者標識(如果設定)來檢驗查詢是否合法。

如果查詢的雜湊值和我們計算的不匹配,我們會返回無權訪問(403)。不用擔心,通過暴力破解來反解API金鑰需要幾年和數萬核心。

你可能希望使用安全過濾但是不關心查詢比率的限制,所以如果你需要這些特性,你只可以只用一個。

幾周前我們推出這個新的特性,並且目前受到很好的反饋。我們的客戶不需要再安全和查詢速度中作出選擇。

如果你看到任何可以改善這個方法的方法,我們將很樂意聽到你們的反饋。

相關文章