2013-02-28 47 views
7

很多有關RESTful Web服務的示例都沒有考慮到今天許多應用程序都是多用戶的問題。什麼是授權和構建RESTful後端的正確方式

想象一下多用戶後臺暴露了一個RESTful API。後端數據體系結構使用共享數據庫和共享模式。每個表將包含一個tenant_id參考:

+-------------+----+-----------------+ 
| tenant_name| id | shared_secret | 
+-------------+----+-----------------+ 
|   bob | 1 | 2737sm45sx543 | 
+-------------+----+-----------------+ 
|  alice | 2 | 2190sl39sa8da | 
+-------------+----+-----------------+ 

+-------------+----+-------+-----------+ 
| pet_name | id | type | tenant_id | 
+-------------+----+-------+-----------+ 
|  fuffy | 1 | dog |   1 | 
+-------------+----+-------+-----------+ 
|  kerry | 2 | cat |   2 | 
+-------------+----+-------+-----------+ 

問題1:與三個或更多與REST風格的後端交互的客戶端應用程序(例如Android,iOS和Web應用程序),你會如何進行認證對後端?

RESTful backend, API, HTTP-Verbs, shared database and schema 
| 
| 
+---- Web Application (Client 1) 
|  | 
|  + Alice 
|  | 
|  + Bob 
| 
+---- Android Application (Client 2) 
|  | 
|  + Alice 
|  | 
|  + Bob 
| 
+---- iOS Application (Client 3) 
|  | 
|  + Alice 
|  | 
|  + Bob 
| 

每個客戶端都應該允許Alice和Bob管理她/他的寵物。每個客戶端都是一個GUI,它將使用(內部發出HTTP請求)後端。問題:每個客戶如何才能對後端進行身份驗證?

假設HMAC(它完全是RESTful,沒有會話):這種方法涉及使用共享密鑰簽名有效載荷(從未通過線路發送)。是否每個客戶都有自己的tenant表(其中包含shared_secret字段)的副本?

Android App -> Client Sign -> Signed Request -> Backend -> Result 
    Web App -> Client Sign -> Signed Request -> Backend -> Result 

問題2:又該資源URI的樣子?

這裏有方法可以得到Bob的寵物兩種可能性:

可能性#1:Authorization頭給你租戶的(唯一的)名稱:

GET /pets HTTP/1.1 
Host: www.example.org 
Authorization: bob:c29kYW9kYSBhb2lzYWRoIGYgZDUzNDUz 

可能性2#。該tenant_id被作爲查詢參數:

GET /pets/tenant_id=1 HTTP/1.1 
Host: www.example.org 
Authorization: bob:c29kYW9kYSBhb2lzYWRoIGYgZDUzNDUz 
+0

使用短語multi-tenant時要小心。我不相信它意味着你的想法。在這裏看到細節http://msdn.microsoft.com/en-us/library/aa479086.aspx – 2013-03-04 19:23:45

+0

@Gaz_Edge它意味着虛擬分區數據在客戶端和單個實例將服務更多的客戶,這就是我正在做的事情。你同意嗎? – gremo 2013-03-04 20:28:01

+1

我覺得你太過於複雜了。您有1個Web服務,n個Web服務客戶端和x個用戶是? – 2013-03-04 22:28:02

回答

4

第1部分

(大聲告訴你:??您是否已決定使用HTTP和HMAC如果是這樣,你爲什麼要問我們)

我建議HTTPS使用基本驗證。簡單。畢竟,Stripe已經足夠好了。

參考文獻:

更新:下面是關於如何處理身份驗證一些額外的細節:

  1. 每個客戶端應用程序將使用API​​密鑰聯繫服務。使用HTTPS和基本身份驗證,客戶端將提供其API密鑰作爲基本身份驗證用戶名。它不需要提供密碼,因爲它使用的是HTTPS。你需要指定一個API密鑰對每個應用程序(Web應用程序,安卓,iOS版),我看到了兩個方面:

    A.一種選擇是,得到跨客戶端共享的每個用戶一個API密鑰。

    B.另一種選擇是給每個客戶一個獨特的應用。)

  2. 但你如何拿到鑰匙到客戶擺在首位?構建「關鍵請求」API端點。我建議給每個客戶端一個「啓動器」鍵,只用於聯繫這個端點。 (起始鍵不允許其他訪問。)當用戶第一次使用客戶端時,他/她必須進行身份驗證。客戶端將其傳遞給「密鑰請求」端點,以便它可以生成與用戶關聯的密鑰。從那以後,每個客戶端都有一個客戶端綁定的API密鑰。

第2部分

考慮給每個租戶的子域。如果您使用的Rails(或者可能是任何現代的網絡堆棧),您可以使用子域名查找租戶ID。那麼你的API可用於這樣的:

GET http://tenant1.app.co/pets 
GET http://tenant2.app.co/pets 
GET http://tenant3.app.co/pets 

引用(Rails的具體的,但應該是整個網絡棧有幫助):

注:如你的例子表明,爲了簡單起見,我將不屬於R爲不同的租戶電子使用同一個寵物ID。例如,下面是一個簡單的路要走:

GET http://tenant1.app.co/pets/200 
GET http://tenant2.app.co/pets/201 
GET http://tenant3.app.co/pets/202 

我所描述的方法是不是通過tenant_id作爲查詢參數清潔得多。此外,使用tenant_id作爲參數感覺不對。我喜歡用的參數更多的「算法」的事情,正如我在「REST Web服務」,由Ruby和理查德森閱讀。

參考文獻:

+0

我喜歡第2部分,我會去尋找子域名。但是第1部分沒有解釋驗證每個應用程序對後端的挑戰。也許這是我可憐的英語,我無法深入解釋這個問題。我選擇了HMAC,因爲請求之間沒有狀態。爲什麼你建議Basic? – gremo 2013-03-08 15:18:02

+0

我建議使用HTTPS + Basic Auth,因爲這是最簡單的方法。如果你想挖掘所有的優點和缺點,我提供了參考。 – 2013-03-08 17:48:22

+0

@Gremo,我剛剛添加了關於第1部分(auth)的一些額外的細節。 – 2013-03-08 18:07:46

3

通過「多租戶」你僅僅意味着應用程序/ Web服務用戶?多租戶通常意味着更復雜的東西msdn.microsoft.com/en-us/library/aa479086.aspx

您需要使用Web服務對每個用戶進行身份驗證。這可以通過SSL的基本http身份驗證完成。

從Web服務的角度來看,您將對所有三個客戶端執行相同的身份驗證。該服務不關心客戶的類型 - 這就是要點。您可能需要爲您的客戶提供不同的表示形式,例如XHTML或JSON。我喜歡將事情簡單化並始終選擇JSON。

對於資源,管理它們的最簡單方法是將用戶資源作爲最高級別,然後將每個用戶的所有資源鏈接在一起,例如,

GET users/fred/pets - returns all pets for user fred 
GET users/fred/pets/sparky - returns details on freds pet sparky 

這樣做的好處在於您可以添加代碼來授權每個請求,例如你可能有兩個用戶,fred和jack。兩個用戶都會通過身份驗證,但你只應該允許fred請求他的資源和插口來請求他的。您只需在您的API中添加授權檢查,例如從URI獲取用戶名,獲取經過身份驗證的用戶的用戶名,並檢查它們是否相同。如果不返回類似http 403的內容,如果它們相同,則允許請求。

我想如果你還不清楚,你需要閱讀REST的細節。到目前爲止,關於這個問題的最好的書是這一個RESTful Web Services。它涵蓋了來自第一原則的REST。它在設計資源,以及如何管理用戶和多個客戶端方面也有非常好的一面。

+0

我會編輯問題以使其更加清晰。與此同時:我只有一個Web服務(RESTful後端)和'n'可能的客戶端(應用程序)使用它。用戶(租戶)將使用其中一個'n'客戶端(可能甚至更多,即webapp和android客戶端)。 – gremo 2013-03-04 17:49:44

+0

我想給Gaz一個upvote,所以他/他沒有得分666. – 2013-03-08 14:11:47

+0

awww,但我喜歡它! ;-) – 2013-03-08 16:50:08

1

我不確定要理解這個問題,因爲在這種情況下多租戶似乎有點矯枉過正。 但是我可以嘗試回答第二個問題。

REST是一種「資源化」的建築,你必須認識到/pets/pets/?tenant=1並不是指在相同的資源:

  • /pets是指當前用戶的寵物,
  • /pets/?tenant=1指鮑勃的寵物。

雖然這兩種解決方案都不對,但通常情況下最好是獲得第二種解決方案。 URI的確被設計爲共享,並且你有更多的理由來分享「Bob的寵物」(即使它需要認證和授權來表示),而抽象的「我的寵物」對每個用戶都不相同。

Should resource ids be present in urls?了類似的討論......

1

如果HTTP協議的所有3客戶端類型使用,你應該只需要實現一個認證方案。你可以選擇你的毒藥 - BasicDigest,Oauth2Cookie是一些常用的方法。由於它是通過HTTP,我沒有理由複製這個邏輯。根據您的平臺,可能有幾個框架將爲您抽象。

要區分客戶端類型,可以使用HTTP標頭user-agent可能已經使這成爲可能。另一種選擇是使用您定義的自定義標題。任何HTTP客戶端都可以設置標題,任何服務器都可以處理自定義標題。一個體面的web框架將相對容易地爲您提供這些框架。作爲後端服務,我懷疑您會希望統一處理所有客戶端請求 - 或儘可能多地處理。當然,維護一個後端優於三個

至於你的API應該是什麼樣子 - 這完全取決於你。爲了保持RESTful,how to GET a cup of coffee非常值得閱讀 - 插入強制性鏈接Roy Fielding's thesis。機會是,你真正想要的是編寫'資源'鏈接的指南。

如果用戶可能需要訪問系統中的所有寵物,則在您列出的選項中,首選第二個,即/pets?userId=bob。如果用戶只需要訪問他們的寵物,則首選/pets

相關問題