【问题标题】:Passing api keys to rest api将 api 密钥传递给 rest api
【发布时间】:2012-01-23 22:45:19
【问题描述】:

我正在使用 phil sturgeon REST_Controller 为 codeigniter 创建一个 REST api,到目前为止,我已经能够创建一个简单的库来为用户生成 api 密钥。 我现在的问题是为每个请求将 api 密钥发送到 API,我如何做到这一点而不必为每个请求手动发送它。

【问题讨论】:

    标签: php codeigniter rest api-key


    【解决方案1】:

    您应该查看请求签名。一个很好的例子是Amazon's S3 REST API。

    概述实际上非常简单。用户有两个重要的信息可以使用您的 API,一个公共用户 ID 和一个私有 API 密钥。他们将公共 ID 与请求一起发送,并使用私钥对请求进行签名。接收服务器查找用户的密钥并确定签名请求是否有效。流程是这样的:

    1. 用户加入您的服务并获得用户 ID(例如 123)和 API 键。
    2. 用户想要向您的 API 服务发出请求以更新他们的电子邮件地址,因此他们需要向您的 API 发送请求,也许是 /user/update?email=new@example.com。
    3. 为了能够验证请求,用户在调用中添加了用户 ID 和 签名,因此调用变为 /user/update?email=new@example.com&userid=123&sig=some_generated_string
    4. 服务器接收到调用,发现它来自 userid=123,并查找该用户的 API 密钥。然后它复制从数据创建签名的步骤,如果签名匹配,则 请求有效。

    此方法可确保 API 密钥永远不会作为通信的一部分发送。

    看看 PHP 的 hash_hmac() 函数,它在发送签名请求时很受欢迎。通常,您会让用户执行一些操作,例如将所有参数放入一个数组中,按字母顺序排序,连接成一个字符串,然后 hash_hmac 该字符串以获取 sig。在此示例中,您可能会这样做:

    $sig = hash_hmac("sha256",$params['email'].$params['userid'],$API_KEY)
    

    然后如上所述将$sig 添加到 REST url。

    【讨论】:

    • 只是想理解这一点,因为我正在尝试做这样的事情.../user/update?email=new@example.com&userid=123&sig=some_generated_string 现在不能有人劫持some_generated_string 并发送它,就好像它来自他们自己一样? (我敢肯定他们不能,但也许你能告诉我为什么?)
    • @jasondavis - 是的,有人可以嗅探那个特定的请求,这是真的。但是因为每个请求的签名都是不同的,所以嗅探它们并没有什么好处。充其量,他们所能做的就是发送完全相同的请求!他们无法生成恶意请求,因为要做到这一点,您需要 API 密钥。如果他们试图破坏他们嗅探到的请求中的数据,比如将电子邮件更改为evil@example.com,签名将不再匹配,并且 REST 服务器将在尝试验证请求时拒绝该请求。
    • 如果用户从 javascript 发出请求并因此将他们的 API 密钥暴露给全世界,这种方法是否不安全?有人可以查看源代码、获取 API 密钥并使用相同的方法生成有效请求以调用服务器。还是我错过了什么。
    • @zombat (我不这么认为,但无论如何..)当用户填写 html 表单时,有没有办法做到这一点?当我说“用户”时,我指的是注册用户,而不是通过存储秘密 api 密钥的本地 PHP 文件发送请求的开发人员。如果没有,我该怎么办?
    • @zombat 这是 baris-usakli 提出的一个非常好的问题。如何在 javascript Web 应用程序中隐藏 API 密钥?对于使用相同 API 的手机应用市场,即使有如何为每个下载的手机应用创建私有 API 并让 API 知道呢?
    【解决方案2】:

    REST 的理念是它是无状态的,因此没有会​​话或任何东西。如果您想进行身份验证,那么这就是密钥的来源,并且必须为每个请求传递密钥,并且每个请求都会对用户进行身份验证(因为 REST 是无状态的,我是否提到过这一点?)。

    您可以通过多种方式传递密钥。您可以将其作为参数传递(即http://example.com/api/resource/id?key=api_key),也可以将其作为 HTTP 标头的一部分传递。我见过指定您发送用户名和 API 密钥作为 HTTP 基本访问授权标头的密码部分的 API。

    一个示例请求:

    <?php
    
    $ch = curl_init();
    curl_setopt_array($ch, array(
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_URL => 'http://example.com/api/resource/id',
        CURLOPT_USERPWD => 'martinbean:4eefab4111b2a'
    ));
    $response = curl_exec($ch);
    

    martinbean 是我在您网站上的帐户用户名,4eefab4111b2a 是我的 API 密钥。

    【讨论】:

    • 这种方法很简单,但本质上是不安全的。有人可以轻松地嗅探您的 API 密钥并开始为自己使用它。如果您希望您的 API 密钥是私有的,您不希望将它们作为请求的一部分发送。
    • Campaign Monitor 将在他们的客户第一次因为在星巴克使用开放无线连接而被劫持 API 密钥时进行大量解释。
    • 访问令牌是一种常用方法,但 API 密钥不是。访问令牌过期,所以如果一个被泄露,它不会是一个大的安全漏洞。但是如果我有你的 API 密钥,我可以生成任意数量的访问令牌。所有这些服务都给你一个“秘密”密钥是有充分理由的……它应该是一个秘密。任何让您传递密钥的服务都是错误的。
    • 请注意,Campaign Monitor(截至 2017 年)使用 HTTPS URL 来传递其 API 密钥,因此它是安全的。不确定这在 2011 年是否属实,当时@zombat 指出这样做很危险。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 1970-01-01
    • 1970-01-01
    • 2017-01-31
    • 1970-01-01
    • 2020-10-13
    相关资源
    最近更新 更多