【问题标题】:Building Secure Public API with PHP/MYSQL使用 PHP/MYSQL 构建安全的公共 API
【发布时间】:2011-02-04 17:21:58
【问题描述】:

我目前正在为一个非常繁忙的互联网网站构建 API。它是用 PHP 和 MySQL 编写的。现在这是我正在编写的第一个 API,它允许人们远程访问他们的帐户。 API 上线后,开发人员将能够使用它编写自己的工具。

现在我可以使用 API,但我不确定它是否完全安全。

一个可行的示例 URL 是:http://domain.com/api.php?api_option=list&api_user_name=USERNAME&api_user_password=PASSWORD

USERNAME: 是用户的实际用户名

PASSWORD: 是他们实际密码的 MD5 编码字符串。

如果详细信息匹配,则返回结果,如果不匹配,则返回错误。

所有外部$_GET 输入都得到mysql_real_escape_string() 处理。

我想让事情变得简单,但我不确定这种方式是否是一种安全的方式,可以让公共 API 直接利用用户帐户数据。

非常感谢您的想法和建议。

【问题讨论】:

  • 在 URL 中包含密码哈希并不是一个好主意。更好的方法可能是拥有一个 API 密钥 - 它在用户和 API 之间调用某种形式的身份验证。
  • 感谢所有 cmets,OAuth,对于我的需要来说似乎有点复杂,所以我正在构建自己的 API 密钥设置。我有一些工作,其中身份验证密钥存储在数据库中,并且 user_id 链接到它。此设置有效,但用户仍需要获取此密钥,如果其他人使用此 API 构建工具,用户需要能够使用他们注册的用户名/密码登录。所以我仍然看不到如何绕过一个初始的 $_GET url,它可以接收用户名和密码来远程生成 API 密钥。
  • 建议: 1. 至少使用安全超文本传输​​协议 (HTTPS) 而不是 HTTP。 2. 通过 POST 发送登录信息(不是通过 URL/GET,因为它们会出现在日志中)

标签: php mysql api


【解决方案1】:

为了互联网的爱,请不要这样做。我恳求您花时间为您的 API 实施 OAuth。请。拜托拜托。

看看这个:http://toys.lerdorf.com/archives/55-Writing-an-OAuth-Provider-Service.html

【讨论】:

  • 你真的必须使用 OAuth 吗?我不喜欢……(虽然我同意上述方法不好/不安全)
  • @o1iver:我推荐 OAuth 只是因为它相当普遍并且已经写了很多关于它的文章,特别是因为显然不能信任 OP 提出他自己的安全实现。不过,任何基于令牌的授权系统都会比他目前正在做的更好。
  • 好的,我同意你关于基于令牌的身份验证的观点,我只是不喜欢 OAuth :-)
  • @o1iver:没关系,哈哈。随意添加您自己对令牌身份验证系统的建议,我很好奇其他人使用什么(我只曾有过使用 OAuth 和 OAuth 衍生产品的乐趣)。
  • 在发现我不喜欢 OAuth 后,我目前正在做一些事情。但我现在只是在尝试不同的东西......所以不能真正贡献太多:-)
【解决方案2】:

请勿使用密码进行 API 许可,即使它已编码,尤其是使用 MD5 编码时。此外,我也不会使用用户名。让用户生成密钥。您使某人能够知道访问用户帐户所需知道的 50%,并且 MD5 有很多站点,您可以将其反转并找到密码匹配项。密钥无疑是最好的方法,因此开发人员可以出于安全目的进一步重新生成它。始终考虑安全性。

【讨论】:

    【解决方案3】:

    如何使用 HMAC_SHA1 和用户密码对请求进行签名?例如,您的网址:http://domain.com/api.php?api_option=list&api_user_name=USERNAME&api_user_password=PASSWORD

    添加时间戳和/或随机字符串(nonce)并构建规范化 base_string:

    $base_string = "api_option=list&api_user_name=USERNAME&timestamp=1296875073&nonce=hgg65JHFj";
    $signature = hmac_sha1($base_string, PASSWORD);
    

    那么新的 URL 将是: http://domain.com/api.php?api_option=list&api_user_name=USERNAME&timestamp=1296875073&nonce=hgg65JHFj&signature=kfvyhgfytgyr6576yfgu

    你的服务器做的是获取所有选项,不包括签名,然后使用相同的方法生成签名,并与客户端发送的签名进行比较,应该是相同的。

    【讨论】:

    • 嗨,Arvin,感谢您的回复。我开始有了大致的想法。您能否对以下设置发表评论。 1. 网站管理员注册使用唯一的 webmaster_api_key 2. $_POST 请求只能通过 https 向 apilogin.php 发出,其中包括 'username','password','webmaster_api_key','timestamp'。 3. apilogin.php 会运行 $base_string = "username+timestamp+webmaster_api_key"; $signature = hash_hmac('sha512', $base_string, $password);如果登录详细信息有效,则返回 $signature。这个 $signature 被记录在一个会话数据库中,并且 user_id 链接到它。
    • 另外,我不是 100% 确定如何处理会话的到期时间。我猜用户希望在某些情况下长时间保持登录状态。此外,用户可能希望使用各种工具保持登录状态,这意味着数据库中存储的各种会话仅适用于 1 个用户。除了有人点击注销之外,什么会使会话过期?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 1970-01-01
    相关资源
    最近更新 更多