3

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

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

并且服务器在json. 我现在的问题是,我怎样才能确保这个 API_KEY 只能由该用户使用?因为如果他发出 AJAX 请求,其他人可以看到带有 API_KEY 的链接并将其用于他的项目。我想允许 AJAX 请求。

4

8 回答 8

4

谁拥有它API_KEY应该被视为“那个用户”,所以如果你想保留“原子”请求(api_key每个请求的一部分,并且没有请求需要依赖于以前的请求),那么你真的不能做太多事情。但是您可以尝试通过摆脱所说的“原子性”来改变 API 工作方式的其他方法。在该模型中,它需要任何 api 方法来调用session_key而不是api_key,并且您api_key应该只用于生成临时 session_key的(除了 API 之外的那种login- 说login那里的方法)。然后所有进一步的调用都需要login返回 session_key。在这种情况下,您可以控制(和限制)使用 single 创建的会话数api_key,或者即login叫做。

于 2013-08-20T12:39:52.087 回答
4

您为什么不尝试在自定义标头中发送您的 API_KEY,该标头可以与来自客户端的 php 或 ajax 请求一起触发,这样您的 API_KEY 在 URL 中根本不可见,稍后可以从服务器使用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 作为查询字符串,您必须发送用户 ID 或任何其他唯一标识符,以便与数据库中的 api_key 相关.

在客户端:

按照给出的 HMAC 做https://code.google.com/p/crypto-js/#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,您可以找出它的好处。

于 2013-08-26T12:53:08.977 回答
2

如果 API 密钥以任何方式、形状或形式在客户端上可见,则访问该页面的用户也可以代表 API 用户提出请求,只要他们是“高级用户”足以检查代码和/或HTTP 请求。无论您是否有加密,是否接受 URL、cookie 中的密钥或任何其他方法......这些其他方法可能会带来一些不便,但知道足以开始搜索 API 密钥的用户也可能足够了解听说过Fiddler之类的。

这就是为什么 API 通常不会让自己对 JavaScript(即 AJAX)可用,而仅对直接请求可用的原因 - 服务器将是发出请求的人,因此它不需要向其透露其 API 密钥它的用户就是这样。

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

于 2013-08-26T13:53:04.123 回答
1

仅使用(有效的公共)API 密钥是不可能的。您需要的是使用密钥的加密身份验证。带有客户端证书的TLS应该可以做到这一点。

于 2013-08-20T12:42:22.303 回答
1

也许不是一个 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 调用,并将在大约一天后过期。

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

于 2013-08-23T15:08:30.140 回答
1

与其将所有数据都放在 url 中,不如使用 POST 方法,让所有数据在后台发送。然后,您可以在页面之间(使用隐藏字段)或使用会话发布他们的 id 和其他数据。

于 2013-08-23T22:32:12.143 回答
1

您可以在 Web 服务中提取 cookie。然后,Web 服务器可以使用身份验证 cookie 来验证 Web 服务调用。我确定您使用的任何框架工作都有一个身份验证令牌存储在浏览器某处的 cookie 中,并且某处有一个 php 片段来对其进行身份验证。

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

欢迎您使用 Web 服务。主页上有一个按钮,上面写着“ASP 认证的测试按钮它说你好,除非你登录”,在你的浏览器上放置一个跟踪并单击它。

用户访客密码 abc123$

您也可以通过我网站上的网络服务登录,但那是另一篇文章 Good Luck

于 2013-08-26T03:29:18.023 回答
0

如果您真的希望它安全,请使用Oauth身份验证(适用于您的情况,为 2-legged 变体)。当然,您也可以使用 HMAC 身份验证或密钥交换,正如其他作者所建议的那样,但使​​用现有的和经过验证的协议总是一个更好的主意,而不是自己发明。

看:

于 2013-08-29T23:57:47.703 回答