2010-01-14 129 views
14

我被要求爲應用程序(pc可執行文件,而不是web-app)編寫Web API,以允許發送電子郵件。
用戶點擊了一些東西,應用程序就會與生成電子郵件的API通信並將其發送出去。Web API安全

我必須確保沒有人擅自訪問API,因此我需要進行某種身份驗證,但我還沒有想到如何正確執行此操作。

將有更多的應用程序訪問API。

首先想到的是 - 發送用戶名和密碼,但這並沒有真正解決問題。因爲如果某人反編譯應用程序,他們將擁有請求url和變量,包括用戶名/密碼或者只是簡單地被嗅探。

so ...我有什麼選擇?

我相當確信安全連接(SSL)目前尚未提供給我,但仍然無法幫助我解決反編譯問題,對嗎?


編輯

我沒有說,最初,但用戶不會被要求輸入用戶名/密碼。應用程序必須經過身份驗證,而不是應用程序的用戶。

回答

8

我建議您查看OAuth。它肯定會幫助您利用授權工具來解決安全問題以訪問您的API。

http://oauth.net

+0

這看起來像我正在尋找的。謝謝! – 2010-02-04 23:41:56

3

有人總是能夠反編譯和尋找變量。混淆器可能會將它們隱藏得更好一些。如果沒有SSL,嗅探也很容易,除非您使用私鑰和公鑰集來加密請求數據客戶端並解密服務器端(但顯然這個密鑰將存儲在客戶端應用程序中)。

要做的最好的事情是提供儘可能多的保護層,您認爲您需要,創建一個安全的連接和混淆您的代碼。你可以看看下面的文章,這表明沒有使用SSL安全連接:

http://www.codeproject.com/KB/security/SecureStream.aspx

正如mattjames提到的,你永遠不應該存儲在純文本格式的密碼。當用戶將密碼輸入到應用程序中時,存儲密碼的散列。應該在服務器上存儲相同的散列值。這樣,如果哈希被攔截器看到,他們至少不會看到用戶的原始密碼。

20

軟件的分佈確實是問題的癥結所在。散列用戶名和密碼並將它們存儲在軟件中並不比存儲未哈希值更有用,因爲任何人都可以訪問API服務器。如果您要爲用戶實現用戶名和密碼,我認爲您可以將它用作API控件的前導,而不必將值存儲在軟件本身中。讓我分兩部分來描述這一點。

請求籤名

在使用API​​請求驗證的最常用的方法是請求籤名。基本上,在將請求發送到API服務器之前,請求中的參數將被排序,並且將一個唯一密鑰添加到混合中。整個批次將被用於生成一個散列,並附加到請求中。例如:

public static function generateRequestString(array $params, $secretKey) 
{ 
    $params['signature'] = self::generateSignature($params, $secretKey); 
    return http_build_query($params,'','&'); 
} 

public static function generateSignature($secretKey, array $params) 
{ 
    $reqString = $secretKey; 
    ksort($params); 
    foreach($params as $k => $v) 
    { 
     $reqString .= $k . $v; 
    } 
    return md5($reqString); 
} 

你可以創建一個使用上面的代碼只需調用generateRequestString()方法與你想發送的所有參數的數組的API請求的查詢字符串。祕密密鑰是唯一提供給API的每個用戶的東西。通常,您將用戶ID與簽名一起傳遞到API服務器,並且API服務器使用您的ID從本地數據庫獲取您的密鑰,並使用您構建它的相同方式驗證請求。假設密鑰和用戶標識是正確的,那麼該用戶應該是唯一能夠生成正確簽名的人。請注意,密鑰從未在API請求中傳遞。

不幸的是,這需要每個用戶都有一個唯一的關鍵,這是爲您的桌面應用程序的一個問題。這導致我步驟二。

臨時密鑰

所以你不能與應用程序分發密鑰,因爲它可以被反編譯,並且鍵會全身而退。爲了反制這一點,你可以製作非常短命的鑰匙。

假設你已經實現了桌面應用程序,要求用戶輸入他們的用戶名和密碼的一部分,可以讓應用程序執行的認證請求到服務器。在成功的身份驗證中,您可以返回臨時密鑰和響應,然後桌面應用可以在授權會話的生存期內存儲這些響應,並用於API請求。因爲您提到您無法使用SSL,所以此初始身份驗證是最容易受到攻擊的部分,您必須忍受一些限制。

文章安迪Ë建議是一個好方法(我投它)。基本上是建立一個可用於認證的短期密鑰的握手。相同的密鑰可以用於簽名散列。你也可以抓住機會,只發送未加密的用戶名/密碼並獲得臨時密鑰(它只會發生一次),但是你必須意識到它可能被嗅探。

摘要

如果能建立一個時間的會話密鑰,你就不必存儲在可以反編譯客戶端程序什麼。一次發送到您的服務器的用戶名/密碼應該足以確定這一點。一旦擁有該密鑰,就可以使用它在桌面應用程序中創建請求,並驗證API服務器上的請求。

+6

+1 - 雖然我有一個評論回覆:'散列用戶名和密碼,並將它們存儲在軟件並不比存儲未散列值,任何一個會工作訪問API server'更加有用。雖然這與提問者無關(如他的編輯),但散列用戶密碼的重點在於,如果有人設法獲得散列,他們只能**訪問API而不是用戶的前端帳戶或甚至網絡上的其他服務 - 因爲許多人對不同的網站使用相同的密碼。因此,不要將密碼作爲純文本存儲。 – 2010-01-15 10:51:01