簡體   English   中英

如何確保API請求來自可以執行此操作的特定人員?

[英]How to make sure the API request is made from the certain person who can do that?

我正在為我的網站創建一個API,它有很多信息,比如電影。 我想允許一定數量的請求。 因此,例如,5 $計划每月允許10,000個請求。 用戶注冊,獲取API密鑰然后可以發出請求

http://website.com/index.php?api_key=API_KEY&movie=Titanic

並且服務器在json給出答案。 我現在的問題是,如何確保該API_KEY只能由該用戶使用? 因為如果他發出AJAX請求,其他人可以看到與API_KEY的鏈接並將其用於他的項目。 我想允許AJAX請求。

擁有API_KEY應該被視為“那個用戶”,所以如果你想保留“原子”請求(其中api_key是每個請求的一部分,而且沒有請求需要依賴以前的請求)那么你真的不能做太多關於它。 但是你可以通過擺脫所謂的“原子性”來嘗試其他方法來改變API的工作方式。 在該模型中,它需要使用任何api方法來調用session_key而不是api_key ,並且您的api_key應該僅用於生成臨時 session_keylogin類型,但對於API - 比如login方法)。 然后所有進一步的調用都需要返回session_key login 在這種情況下,您可以控制(並限制)使用單個api_key創建的會話數,或者如果調用新login則終止其他會話。

為什么不嘗試在自定義標頭中發送API_KEY,這些標頭可以與來自客戶端的php或ajax請求一起觸發,這樣就可以在URL中看不到你的API_KEY,以后可以從服務器中刪除apache_request_headers() ,這是一個更安全的方法,如果你仍然apache_request_headers() ,你可以實現HMAC http身份驗證,這是該死的安全,我打賭你。

方法1 :(沒有HMAC)

客戶端:

使用Jquery

$.ajax({
url: 'foo/bar',
headers: { 'api_key': 'API_KEY' }
});

使用PHP

header('api_key':'API_KEY');

通過在請求中添加標題,URL就可以了

http://website.com/index.php?movie=Titanic

在服務器端:

$headers = apache_request_headers();
if(isset($headers['api_key']))
{
// validate your api_key from database
}

方法2 :(使用HMAC)在這種情況下,稍有改動,而不是在您的URL中作為查詢字符串發送API_KEY,您將必須發送userID或任何其他唯一標識符,與數據庫中的api_key相關。

在客戶端:

按照https://code.google.com/p/crypto-js/#HMAC執行HMAC

或者使用php函數hash_hmac()
使用這兩種方法,您將得到一個散列值,它是您的API_KEY和您的數據的組合,例如。 $hashed_value = hash_hmac('sha1','titanic','API_KEY');
header('hash':$hashed_value);

您的網址http://website.com/index.php?movie=Titanic&uid=xx

在服務器端:

$headers = apache_request_headers();
if(isset($headers['hash']))
{
// then try to recreate your hash in server, like
//using $_GET['uid']= get your API_KEY from DB
$api_key = getApiKey($_GET['uid']);
$hash = hash_hmac('sha1',$_GET['movie'],$api_key);
if($hash==$headers['hash'])
{
// User authenticated }

}

如果您通過HMAC ,您可以了解它的好處。

如果API密鑰以任何方式,形狀或形式在客戶端上可見,訪問該頁面的用戶也可以代表API用戶發出請求,只要他們是“超級用戶”足以檢查代碼和/或HTTP請求。 無論你是否有加密,你是否接受URL,cookie或其他方面的密鑰......那些其他方法可能有點不方便,但知道足夠開始搜索API密鑰的用戶可能也知道足夠聽說過小提琴手等。

這就是為什么API通常不能使自己可用於JavaScript(即AJAX),而只是直接請求的原因 - 服務器將是發出請求的服務器,因此它不需要透露他們的API密鑰它的用戶就是這樣。

除了不允許AJAX使用API​​之外,沒有解決方案。 您應該允許AJAX訪問的唯一一種API是公開可用的API(如“無需登錄”),僅限於IP在N個時間內生成N個請求。

僅使用(有效的公共)API密鑰是不可能的。 您需要的是使用密鑰進行加密認證。 帶有客戶端證書的TLS應該這樣做。

也許不是100%完美的解決方案,但對於您的特定電影業務示例,它應該工作得很好。

首先,您為每個用戶提供用戶名和密碼。

為了進行AJAX調用,用戶必須指定3件事:

  1. 用戶名
  2. 想要的電影ID
  3. API_KEY

現在,API_KEY將是一個哈希(您可以使用sha1()md5()甚至它們的組合),它們基於以下內容生成:

  • 用戶的密碼
  • 想要的電影ID
  • 今天的日期

所以這里大概是用戶為了發出AJAX請求必須做的事情:

$username = 'john_smith';
$password = 'abc';
$movie_id = 'Titanic';
$date = date('Y-m-d');

$API_KEY = sha1($password . $movie_id . $date);

AJAX("http://website.com/index.php?user=$user_name&movie=$movie_id&api_key=$API_KEY");

(類似的情況可以在JavaScript中完成,以防您希望用戶只有客戶端環境。)

在你身邊你必須做如下。 知道用戶名,就可以在數據庫中找到他們的密碼。 從請求中獲取movie_id。 今天的日期我們都知道。 (您也可以查看昨天和明天以避免時區問題。)

然后生成相同的哈希並將其與用戶發送給您的API_KEY進行比較。 如果他們匹配 - 一切都很好。

這樣,您最終將獲得僅對一部電影有效的獨特AJAX調用,並將在大約一天后到期。

我認為這將是一種非常有效的方法,至少在業務方面。

而不是在網址中包含所有數據,為什么不使用POST方法,並在幕后發送所有數據。 然后,您可以在頁面之間(使用隱藏字段)或使用會話發布其ID和其他數據。

您可以在Web服務中提取cookie。 然后,Web服務器可以使用身份驗證cookie來驗證Web服務調用。 我確定你所使用的框架工作在某個地方的瀏覽器中有一個存儲在cookie中的身份驗證令牌,並且在某處有一個用於驗證它的php的snipet。

危險不是這里的php示例。 我在我的網站http://www.gosylvester.com上有一個經過身份驗證的Web服務,它只返回一個hello world但是如果你對它進行了跟蹤並登錄。你會看到身份驗證cookie隨之上下。

歡迎您使用網絡服務。 主頁上有一個按鈕,上面寫着“ASP認證的測試按鈕,除非你已登錄,否則它會打招呼”在你的瀏覽器上添加一條跟蹤並點擊它。

用戶訪客密碼abc123 $

您也可以通過我的網站上的webservice登錄,但這是另一個帖子祝你好運

如果您確實希望它安全,請使用Oauth身份驗證(根據您的情況,使用雙腿版本)。 當然,您也可以像其他作者所建議的那樣使用HMAC身份驗證或密鑰交換,但使用現有和經過驗證的協議始終是一個更好的主意,而不是創建自己的協議。

看到:

暫無
暫無

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

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