2008-10-29 106 views
65

我正在開始爲我正在開發的項目構建REST API,並且這讓我做了一點研究,以瞭解最佳方式使用RoR構建API。我很快發現,默認情況下,模型向全世界開放,只需在URL末尾添加一個「.xml」並傳遞適當的參數即可通過URL調用。尋找在Ruby on Rails中構建安全REST API的建議

那麼下一個問題就來了。如何保護我的應用程序以防止未經授權的更改?在做一些研究時,我發現一些文章談論了attr_accessibleattr_protected以及它們如何使用。我在07年5月發現了關於這些網站的特定網址(here)。

就像所有的事情一樣,我相信事情自那時起就有了進步。所以我的問題是,這仍然是在RoR中保護REST API的最佳方式嗎?

如果不是您在「新項目」或「現有項目」方案中提出的建議如何?

+0

如果客戶端知道如何操作您的URI(通過附加.xml或其他方式),那麼您的API不是REST。 – aehlke 2009-08-18 14:59:32

+0

這是一個很好的Oauth 2.0服務器庫ruby https://github.com/Lelylan/rest-oauth2-server – sparkle 2012-04-05 20:36:16

回答

100

有幾種驗證API請求的方案,它們與插件(如restful_authentication或acts_as_authenticated)提供的常規驗證不同。最重要的是,客戶不會維護會話,所以沒有登錄的概念。

HTTP認證

您可以使用基本的HTTP認證。對於這一點,API客戶端將使用常規的用戶名和密碼,只要把它的URL像這樣:

http://myusername:[email protected]/ 

我相信restful_authentication支持這一開箱即用,因此可以忽略是否有人正在使用您的應用程序通過API或通過瀏覽器。

這裏的一個缺點是您要求用戶在每個請求中都明確地輸入用戶名和密碼。通過SSL實現,可以使其安全。

雖然我不認爲我真的看到過使用此API的API。對我來說,這似乎是個不錯的主意,尤其是因爲它是由當前的認證方案開箱即用的,所以我不知道問題出在哪裏。

API密鑰

另一種簡單的方法來啓用API認證是使用API​​密鑰。它本質上是遠程服務的用戶名。當有人註冊使用你的API時,你給他們一個API密鑰。這需要與每個請求一起傳遞。

這裏的一個缺點是,如果任何人獲取他人的API密鑰,他們可以以該用戶的身份發出請求。我認爲,通過使所有的API請求都使用HTTPS(SSL),您可以稍微抵消一些風險。

另一個缺點是用戶在任何地方都使用相同的認證憑證(API密鑰)。如果他們想要撤銷對API客戶端的訪問,他們唯一的選擇是更改他們的API密鑰,這也將禁用所有其他客戶端。這可以通過允許用戶生成多個API密鑰來緩解。

API密鑰+祕密密鑰簽名

已過時(在某種程度上) - 見下文

複雜得多OAuth是簽署同一個密鑰請求。這就是亞馬遜網絡服務(S3,EC2等)的功能。基本上,你給用戶2個密鑰:他們的API密鑰(即用戶名)和他們的密鑰(即密碼)。 API密鑰隨每個請求一起傳輸,但密鑰不是。相反,它通常通過添加另一個參數來用於簽署每個請求。

IIRC亞馬遜通過將所有參數提交給請求並通過參數名稱對其進行排序來完成此操作。然後,使用用戶的密鑰作爲散列鍵,散列該字符串。這個新值在被髮送之前作爲新的參數附加到請求中。在亞馬遜方面,他們也做同樣的事情。他們採取所有參數(簽名除外),排序他們,並使用密鑰散列。如果這符合簽名,他們知道該請求是合法的。

這裏的缺點是複雜性。讓這個方案正確工作對於API開發人員和客戶來說都是一種痛苦。預計會有很多來自客戶開發人員的支持電話和憤怒的電子郵件,他們無法啓動工作。

的OAuth

爲了解決一些與鍵+祕密簽署的複雜性問題,標準已經出現所謂的OAuth。在覈心OAuth是一個密鑰+祕密簽名的味道,但其中大部分是標準化的,已被納入libraries for many languages

一般來說,API生產者和消費者使用OAuth比創建自己的密鑰/簽名系統要容易得多。

OAuth也固有地分段訪問,爲每個API使用者提供不同的訪問憑證。這允許用戶選擇性地撤銷訪問而不影響其他消費應用程序。

專門針對Ruby,有一個OAuth gem,爲OAuth的生產者和消費者提供開箱即用的支持。我已經使用這個gem來構建一個API並且使用OAuth API,並且給我留下了深刻的印象。如果您認爲您的應用程序需要OAuth(與簡單的API密鑰方案相反),那麼我可以輕鬆推薦使用OAuth gem。

3

我現在正面臨着類似的問題,因爲我還爲Rails應用程序構建了一個REST API。

我建議確保只有可以被用戶編輯的屬性用attr_accessible標記。這將設置一個可以使用update_attributes分配的屬性的白名單。

我做的是這樣的:

class Model < ActiveRecord::Base 
     attr_accessible nil 
    end 

我所有的車型從繼承,使他們被迫定義爲attr_accessible他們希望製造大規模分配的任何領域。就我個人而言,我希望有一種方法可以默認啓用此行爲(可能有,我不知道)。

只要你知道有人可以批量分配一個屬性不僅使用REST API,但也使用常規的形式發佈。

7

如何保護我的應用程序以防止 未經授權的更改?

attr_accessibleattr_protected是用於控制對一個ActiveRecord模型上執行質量分配的能力都非常有用。你一定要使用attr_protected來防止表單注入攻擊;請參閱Use attr_protected or we will hack you

此外,爲了防止任何人能夠訪問Rails應用程序中的控制器,幾乎肯定會需要某種用戶身份驗證系統,並將before_filter放入您的控制器中以確保您擁有在允許請求的控制器動作執行之前,授權用戶發出請求。

請參閱Ruby on Rails Security Guide(Rails文檔項目的一部分)瞭解更多幫助信息。

0

另一種節省構建大量資料的方法是使用類似http://www.3scale.net/的方法,它可以爲個別開發人員處理密鑰,令牌,配額等。它也進行分析並創建開發者門戶。

有一個ruby/rails插件ruby API plugin它將適用於流量到達時的策略 - 您可以將它與oAuth gem一起使用。您也可以通過在應用程序前面清除清漆並使用清漆lib mod:Varnish API Module來使用它。