如何确保API请求来自可以执行此操作的特定人员?

时间:2013-08-20 12:36:58

标签: php javascript json api cryptography

我正在为我的网站创建一个API,它有很多信息,比如电影。我想允许一定数量的请求。因此,例如,5 $计划每月允许10,000个请求。用户注册,获取API密钥,然后可以发出类似

的请求

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

,服务器在json中回复答案。我现在的问题是,如何确保该API_KEY只能由该用户使用?因为如果他发出AJAX请求,其他人可以看到与API_KEY的链接并将其用于他的项目。我想允许AJAX请求。

8 个答案:

答案 0 :(得分:4)

持有API_KEY的人应被视为“该用户”,因此如果您想保留“原子”请求(其中api_key是每个请求的一部分,并且没有请求需要依赖于之前的那些你不能真正做很多事情。但是你可以通过摆脱所谓的“原子性”来尝试其他方法来改变API的工作方式。在该模型中,需要使用任何api方法来调用session_key而不是api_key,并且您的api_key只应用于生成临时 {{1 (session_key的类型,但对于API - 请说login方法。然后所有进一步的调用都需要返回session_key login。在这种情况下,您可以控制(并限制)使用单个login创建的会话数,或者,如果调用新的api_key,则终止其他会话。

答案 1 :(得分:4)

为什么不尝试在自定义标头中发送API_KEY,这些标头可以与来自客户端的php或ajax请求一起触发,这样就可以在URL中看不到您的API_KEY,以后可以从中删除使用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) 在这种情况下,稍有改动,而不是在您的网址中将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,就可以了解它的好处。

答案 2 :(得分:2)

如果API密钥以任何方式,形状或形式在客户端上可见,访问该页面的用户也可以代表API用户发出请求,只要他们是“超级用户”足以检查代码和/或HTTP requets。无论你是否有加密,你是否接受URL,cookie或其他方面的密钥......那些其他方法可能有点不方便,但知道足够开始搜索API密钥的用户可能也知道足够听说过提琴手等。

这就是为什么API通常不能使自己可用于JavaScript(即AJAX)的原因,而只是直接请求 - 服务器将是发出请求的人,因此它不需要透露他们的这种方式为其用户提供API密钥。

除了不允许AJAX使用API​​之外,没有解决方案。您应该允许AJAX访问的唯一一种API是公开可用的API(如“无需登录”),仅限于IP在N个时间内生成N个请求。

答案 3 :(得分:1)

仅使用(有效的公共)API密钥是不可能的。您需要的是使用密钥进行加密认证。带有客户端证书的TLS应该这样做。

答案 4 :(得分:1)

也许不是100%完美的解决方案,但对于您的特定电影业务示例,它应该可以正常运行。

首先,您为每个用户提供用户名和密码。

为了进行AJAX调用,用户必须指定3件事:

  1. 用户名
  2. 所需的电影ID
  3. API_KEY
  4. 现在,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调用,并且将在大约一天后过期。

    我认为这将是一种非常有效的方法,至少在商业方面。

答案 5 :(得分:1)

而不是在url中包含所有数据,为什么不使用POST方法,并在幕后发送所有数据。然后,您可以在页面之间(使用隐藏字段)或使用会话发布其ID和其他数据。

答案 6 :(得分:1)

您可以在网络服务中提取Cookie。然后,Web服务器可以使用身份验证cookie来验证Web服务调用。我确定你所使用的框架工作在某个地方的浏览器中有一个存储在cookie中的身份验证令牌,并且在某处有一个用于验证它的php。

危险不是这里的php示例。   我在我的网站http://www.gosylvester.com上有一个经过身份验证的Web服务,它只返回一个hello world但是如果你对它进行了跟踪并登录。你会看到身份验证cookie随之上下。

欢迎您使用网络服务。主页上有一个按钮,上面写着“ASP认证的测试按钮,除非你已登录,否则它会打招呼”在你的浏览器上点了一下并点击它。

用户访客密码abc123 $

您也可以通过我的网站上的webservice登录,但这是另一篇文章 祝你好运

答案 7 :(得分:0)

如果您确实希望它安全,请使用Oauth身份验证(根据您的情况,使用双腿版本)。当然,您也可以像其他作者所建议的那样使用HMAC身份验证或密钥交换,但使用现有和经过验证的协议始终是一个更好的主意,而不是创建自己的协议。

请参阅: