2009-01-19 58 views
67

我目前正在研究.net的REST庫,並且我想聽聽關於我擁有的一個開放點的一些意見:REST和身份驗證。REST和身份驗證變種

這裏是與庫中使用的RESTful接口的一個示例:

[RestRoot("/user")] 
public interface IUserInterface 
{ 
    [RestPut("/")] 
    void Add(User user); 

    [RestGet("/")] 
    int[] List(); 

    [RestGet("/get/{id}")] 
    User Get(int id); 

    [RestDelete("/delete/{id}")] 
    void Delete(int id); 
} 

服務器代碼然後只是實現接口和客戶端可以通過工廠獲得相同的接口。或者,如果客戶端不使用該庫,則標準HTTP請求也可以使用。

我知道有使用HTTP基本身份驗證或向需要驗證用戶的請求發送令牌的主要方法。

第一種方法(HTTP基本驗證),有以下問題(具體部分網絡瀏覽器):

  • 密碼的每個請求發送的 - 即使SSL這有某種「壞感覺」 。
  • 由於密碼是通過請求頭傳輸的,因此本地攻擊者很容易查看傳輸的頭文件以獲取密碼。
  • 密碼在瀏覽器內存中可用。
  • 沒有標準的方式來過期用戶「會話」。
  • 使用瀏覽器登錄會中斷頁面​​的外觀。

第二個方法的問題是更側重於實施和庫使用:

  • 每個請求的URI這就需要認證必須有令牌,這只是很重複的參數。
  • 如果每個方法實現需要檢查令牌是否有效,那麼需要編寫更多的代碼。
  • 該界面將變得不那麼具體,例如[RestGet("/get/{id}")][RestGet("/get/{id}/{token}")]
  • 在哪裏把令牌:在URI的末尾?根後?別的地方?

我的想法是把令牌作爲參數傳遞到像http:/server/user/get/1234?token=token_id的URL。

另一種可能性是將參數作爲HTTP標頭髮送,但這會使我用普通的HTTP客戶端的使用變得複雜。

令牌將作爲每個請求上的自定義HTTP標頭(「X-Session-Id」)傳遞迴客戶端。

然後這可以從接口完全抽象出來,並且任何需要認證的實現都可以詢問令牌(如果給定)屬於哪個用戶。

您認爲這會違反REST嗎?或者您有更好的想法嗎?

回答

63

我傾向於認爲認證細節屬於標題,而不是URI。如果您依賴於放置在URI上的令牌,則應用程序中的每個URI都需要進行編碼以包含該令牌。這也會對緩存產生負面影響。具有不斷變化的標記的資源將不再能夠被緩存。與資源相關的信息屬於URI,而不是與應用相關的數據,例如憑證。

看來您必須將Web瀏覽器定位爲客戶端?如果是這樣,您可以使用HTTP Digest access authentication或向客戶端頒發自己的SSL證書進行調查,以唯一標識和驗證它們。另外,我不認爲會話cookie肯定是壞事。特別是在處理瀏覽器時。只要你隔離了cookie處理代碼,並讓其他應用程序不依賴它,你就沒事了。關鍵只是在會話中存儲用戶的身份,沒有別的。不要濫用服務器端會話狀態。

如果你的目標瀏覽器以外的客戶,然後也有一些你可以採取的辦法。我曾運用過亞馬遜的S3 Authentication機制。

這當然都是非常主觀的。純度和跟隨REST到信有時可能是不切實際的。只要您儘量減少並隔離這些行爲,應用程序的核心仍然可以是RESTful。我強烈建議將RESTful Web Services作爲REST信息和方法的重要來源。

4

我見過的其他身份驗證將會話視爲創建,銷燬等REST資源,然後會話ID傳遞來回。我見過的人傾向於使用會話cookie,因爲這是確保安全的唯一方法。如果您在URL中傳遞會話標識,則您無法通過正確的客戶端進行真正的身份驗證。

認證是一個棘手的問題,REST不過,因爲它需要某種形式的狀態的,以保持它侵犯URL爲所需來表示狀態的所有REST原理的URL的外部。

+0

因爲它將永諾使用SSL如果不是在一個安全的網絡內部使用,使用會話的UUID的是那裏來的不應該是一個問題。 什麼阻止某人僞造cookie? – Fionn 2009-01-19 18:34:49

+3

我不會說擁有URI是代表狀態所需的全部是REST的一個原則。相反,資源是可尋址的,並且請求中包含的所有應用程序狀態似乎是一種更好的方式來陳述它。 – laz 2009-01-21 20:25:49

+0

您可以使用MAC保護Cookie,例如該服務器有一個祕密,並會發放給客戶端以下會話令牌: _ 其中MAC被構造爲SHA1( _ ) 當客戶端發送一個令牌 _ 服務器必須檢查 _ 等於 ordnungswidrig 2010-02-11 09:15:25

16

我同意workmad3,如果會話壽命需要保持你應該創建一個會話資源。使用用戶憑證(基本身份驗證或身份內容中的憑證)在該資源上發佈將返回唯一的會話ID。刪除/會話/ {id}會註銷用戶。

如果您想控制會話到期時間。當創建新會話時(在會話資源上發佈),服務器將在響應上設置一個cookie(使用標準的set-cookie頭)。 該cookie將包含到期時間。 cookie字符串應該在服務器上加密,所以只有服務器才能打開該cookie。 每次向服務器發送的請求都會在cookie頭中發送會話cookie。 (如果你的客戶端是瀏覽器,它會自動完成)。服務器需要爲每個請求「更新」cookie,即用新的到期時間(擴展會話超時)創建新的cookie。 記得在用戶呼叫會話資源上的刪除時清除cookie。

如果你希望你的應用程序中更安全,你可以存儲在cookie自身的客戶端IP,所以當一個請求到達服務器可以驗證它是從「原始」的客戶端發送。但請記住,當涉及代理時,此解決方案可能會有問題,因爲服務器可能會「看到」來自同一客戶端的所有請求。