簡體   English   中英

無需重新發明輪子即可保護 REST API

[英]Securing REST API without reinventing the wheel

在設計 REST API 時,通常先對用戶進行身份驗證嗎?

我正在尋找的典型用例是:

  • 用戶想要獲取數據。 當然很酷,我們喜歡分享! 獲取公共 API 密鑰並閱讀!
  • 用戶想要存儲/更新數據......哇等等! 你是誰,你能做到嗎?

我想構建一次並允許說一個 web 應用程序、一個 android 應用程序或一個 iPhone 應用程序來使用它。

REST API 似乎是具有這樣要求的合乎邏輯的選擇

為了說明我的問題,我將使用一個簡單的例子。

我在數據庫中有一個項目,它有一個評級屬性(整數 1 到 5)。

如果我正確理解 REST,我將使用我選擇的語言實現 GET 請求,該語言返回 csv、xml 或 json,如下所示:

http://example.com/product/getrating/{id}/

假設我們選擇返回的 JSON:

{
  "id": "1",
  "name": "widget1",
  "attributes": { "rating": {"type":"int", "value":4} }
}

這對於面向公眾的 API 來說很好。 我明白了那部分。

我有很多問題是如何將它與安全模型結合起來? 我已經習慣了網絡應用程序安全性,在這種情況下,我有一個會話狀態始終可以識別我的用戶,因此無論他們決定向我發送什么,我都可以控制他們可以做什么。 據我了解,這不是 RESTful,因此在這種情況下將是一個糟糕的解決方案。

我將嘗試使用另一個使用相同項目/評級的示例。

如果用戶“JOE”想要為一個項目添加一個評分

這可以使用:

http://example.com/product/addrating/{id}/{givenRating}/

在這一點上,我想存儲數據,說明“JOE”給產品 {id} 的評級為 {givenRating}。

問題:我怎么知道請求來自“JOE”而不是“BOB”。

此外,如果它是為了更敏感的數據,比如用戶的電話號碼呢?

到目前為止我所得到的是:

1) 使用 HTTP 的內置功能對每個請求進行身份驗證,無論是純 HTTP 還是 HTTPS。

這意味着現在每個請求都采用以下形式:

https://joe:joepassword@example.com/product/addrating/{id}/{givenRating}/

2)使用像 Amazon 的 S3 這樣的方法和私鑰和公鑰: http : //www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

3)無論如何都要使用cookie並打破REST的無狀態部分。

第二種方法對我來說似乎更好,但我想知道我真的必須重新發明整個事情嗎? 散列,存儲,生成密鑰等都是我自己嗎?

這聽起來很像在典型的 Web 應用程序中使用 session 並自己重寫整個堆棧,這對我來說通常意味着“你做錯了”,尤其是在處理安全問題時。

編輯:我想我也應該提到 OAuth。

不要擔心“RESTful”,擔心安全性。 這是我的方法:

第 1 步:用戶使用憑據訪問身份驗證服務。

第 2 步:如果憑據檢出,則返回指紋、會話 ID 等,然后將它們彈出到共享內存中以便稍后快速檢索,或者如果您不介意將 Web 服務周轉時間增加幾毫秒,則使用數據庫.

第 3 步:在每個 Web 服務腳本的頂部添加一個入口點調用,以驗證每個Web 服務請求的指紋和會話 ID。

第 4 步:如果指紋和會話 ID 無效或超時,則重定向到身份驗證。

讀這個:

RESTful 認證

5年后編輯

使用 OAuth2!

上一版本

不,絕對沒有必要使用 cookie。 它的安全性不如 HTTP Digest、OAuth 或亞馬遜的 AWS(不難復制)。

您應該看待 cookie 的方式是,它是一個身份驗證令牌,與 Basic/Digest/OAuth/無論哪個一樣,但不太合適。

但是,我認為使用 cookie本身並不違背 RESTful 原則,只要會話 cookie 的內容不影響您從服務器返回的資源的內容即可。

Cookie 是邪惡的,停止使用它們。

3年后編輯

我完全同意 Evert,將OAuth2與 HTTPS 一起使用,並且不要重新發明輪子! :-)

通過更簡單的 REST API - 不適用於 3rd 方客戶端 - JSON Web Tokens也可以很好。

上一版本

無論如何都要使用 cookie 並打破 REST 的無狀態部分。

不要使用會話,使用會話,您的 REST 服務將無法很好地擴展......這里有 2 種狀態:應用程序狀態(或客戶端狀態或會話)和資源狀態。 應用程序狀態包含會話數據,由 REST 客戶端維護。 資源狀態包含資源屬性和關系,由 REST 服務維護。 您可以很容易地確定特定變量是應用程序狀態的一部分還是資源狀態的一部分。 如果數據量隨着活動會話數的增加而增加,則屬於應用程序狀態。 因此例如當前會話的用戶身份屬於應用程序狀態,但用戶列表或用戶權限屬於資源狀態。

因此 REST 客戶端應該存儲標識因素並隨每個請求發送它們。 不要將 REST 客戶端與 HTTP 客戶端混淆。 它們不一樣。 REST 客戶端也可以在服務器端,如果它使用 curl,或者它可以創建例如一個服務器端 http only cookie,它可以通過 CORS 與 REST 服務共享。 唯一重要的是 REST 服務必須通過每個請求進行身份驗證,因此您必須隨每個請求發送憑據(用戶名、密碼)。

  • 如果您編寫客戶端 REST 客戶端,則可以使用 SSL + HTTP 身份驗證來完成。 在這種情況下,您可以在服務器上創建credentials -> (identity, permissions)緩存以加快身份驗證。 請注意,如果您清除該緩存,並且用戶發送相同的請求,他們將獲得相同的響應,只是需要更長的時間。 您可以將其與會話進行比較:如果您清除會話存儲,則用戶將獲得status: 401 unauthorized響應...
  • 如果您編寫服務器端 REST 客戶端並通過 curl 向 REST 服務發送標識因素,那么您有 2 個選擇。 您也可以使用 http auth,或者您可以在 REST 客戶端中使用會話管理器,但不能在 REST 服務中使用。
  • 如果有人不受信任地編寫了您的 REST 客戶端,那么您必須編寫一個應用程序來對用戶進行身份驗證,並讓他們可以決定是否要向不同的客戶端授予權限。 Oauth 是一個已經存在的解決方案。 Oauth1 更安全,oauth2 不太安全但更簡單,我想這個問題還有其他幾種解決方案......你不必重新發明這個。 有使用oauth的完整認證和授權方案,例如: wso身份服務器

餅干不一定是壞的。 您可以以 RESTful 方式使用它們,直到它們保持客戶端狀態並且服務僅保持資源狀態。 例如,您可以在 cookie 中存儲購物車或首選分頁設置...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM