PHP-在2台服务器之间安全地发送请求/响应


PHP - Securely sending request/response between 2 servers?

摘要:我用PHP创建了一个应用程序。这是呼叫中心的潜在客户管理系统。我现在需要允许合作伙伴能够通过将我们的应用程序与他们专有的CRM集成来为应用程序添加新的线索。简而言之,我想我需要为我的应用程序建立一个API。

我能想到的最简单的方法是一个简单的HTML帖子。这会被认为太不安全吗?如果是这样的话,对于这种情况,最好的方法是什么?

感谢您的帮助,

安德鲁。

在构建API的过程中,您很可能会遇到其中的一些。我将概述一些概念,这些概念对于实际构建一个可用的、遵循开放标准的API可能非常有用(反过来,第三方调整现有代码以与之交互变得微不足道(。

API处置

第一个关键字是:SSL。千万不要考虑不使用它。这提供了一个安全的套接字层,在该层上可以以安全的方式进行通信,从而使窃听和MitM攻击变得更加难以想象。

不管怎样,都不要跳过这个。证书的费用不到60美元/年,所以它并不昂贵,从长远来看可以为你节省很多钱。

就服务器技术而言,使用您想要的。您的主要需求是一个能够处理四个常见HTTP谓词的Web服务器:GET、POST、PUT和DELETE。我稍后会解释原因。

API授权

这是一个有争议的领域,因为很多人"认为他们有一个安全的方法"。答案根本不是真的。身份验证的目的是允许客户端轻松地使用其凭据进行身份验证,但防止没有特权的第三方这样做。

简单地在提要中添加API密钥只会导致有人最终掌握它。我已经多次看到这个特定的东西,我强烈建议不要这样做,尤其是因为有更容易的选择。

我将介绍几件事,分别将它们标记为(a(。签名是用于使您的请求不可篡改的方法。身份验证可以证明你是谁。

HMAC-SHA512签名(A((S(

这项技术被亚马逊用于其所有的S3/AWS API,是一种非常轻量级的签名和验证请求的方法。我个人觉得它比较巧妙。

基本理念:

  1. 汇总所有GET和POST字段(包括公钥(
  2. 按字母顺序排序
  3. 使用URLEncode或等效代码将它们连接起来
  4. 使用您的私钥作为HMAC的密钥,对数据执行HMAC哈希密码
  5. 将4的结果附加到您的请求中

这是简单而巧妙的。保证:

  1. 您不能在不知道私钥和公钥的情况下更改请求
  2. 如果不更改请求,就无法更改密钥

这使用相同的HTTP请求巧妙地包装了这两个问题,而只保留了一个GET/POST字段。亚马逊还要求在请求中提供时间戳,以防止重放攻击。整洁的

(参考:HMAC-ALGO=ALGO( (key XOR PAD) concat ALGO(key XOR PAD2) concat message).ALGO可以是任何哈希密码-SHA256是首选的轻量级性质(

OAuth(A(

你可能听说过。这个想法很简单:你会得到一把钥匙和一个秘密。这允许您排队领取临时令牌。然后使用此令牌来执行请求。

这样做的主要优点是存在许多库来处理它,包括客户端和服务器端。另一个优点是OAuth有两种操作模式:两条腿(服务器->服务器,没有客户端交互(和三条腿(客户端->服务器->服务器(。

主要的缺点是两个HTTP请求来获取令牌。

只需通过(A(发送私钥

导致重播攻击。不要考虑。

多种方法是可能的。例如,HMAC标牌与OAuth相结合时非常棒!

API概念

如今,API端点遵循两个主要标准:SOAP(XML-RPC(或REST。如果你正在构建一个发布潜在客户的端点,你也可以构建相应的API来读取潜在客户并在将来删除它们。

因此,您的API将采用以下形式:

 /my/endpoint/
  - GET: gets a list of leads
  - POST: creates a new lead
 /my/endpoint/ID/
  - GET: get lead info
  - PUT: modifies lead
  - DELETE: deletes the lead

这使您也可以方便地对API进行未来的电子编程。

一篇HTML文章就足够了,这不是问题。如果您能够使用HTTPS来确保传输的数据得到编码,那就更好了,但这并不重要。

保护此类API的最常见方法是提供共享的"secret"或"key",用于对哈希进行编码。然后,您将能够验证请求是否来自可信来源,但这取决于用户是否对共享密钥保密。

例如,API的用户需要:

// build hash string to be sent with API POST request (use a sensible combination of values)
$string = sprintf('%s.%d.%d.%d', $username, $orderId, $currentTimestamp, $price);
// hash
$encodedString = sha1($string);
// concatenate with shared key
$stringWithKey = sprintf('%s.%s', $encodedString, $sharedKey); // GET KEY FROM SECURE PLACE
// hash again to get hash that will be sent with the POST request
$hash = sha1($stringWithKey);

然后,您将根据提供的POST值在您的端执行相同的逻辑,并验证它们的哈希是否与您使用用户的共享密钥构建的哈希匹配。

这正是API的作用。我会为每个外部帐户创建一个唯一的密钥,并要求为发送到您的服务器的每个$_GET$_POST事务提供API密钥。

当你在做API管理控制台的时候,可能想建立一个它。哦,不要忘记API键的单独DB表。

当你完成后,它将类似于:

https://api.mysite.com/index.php?key=r328r93fuh3u4h409890fj34klj&other=something&另一个=类似的东西

你明白了。