Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/226.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/security/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Web API安全_Php_Security_Api_Authentication - Fatal编程技术网

Php Web API安全

Php Web API安全,php,security,api,authentication,Php,Security,Api,Authentication,我被要求为允许发送电子邮件的应用程序(pc可执行文件,而不是Web应用程序)编写Web API。 用户点击某个东西,应用程序就会与API通信,API会生成一封电子邮件并发送出去 我必须确保没有未经授权的人可以访问API,因此我需要进行某种身份验证,但我不知道如何正确执行 将有更多的应用程序访问API 第一个想法是发送用户名和密码,但这并不能真正解决问题。因为如果有人反编译应用程序,他们将拥有请求url和包括用户/密码在内的变量,或者只是可以嗅探它 所以。。。我有什么选择 我相当肯定安全连接(SS

我被要求为允许发送电子邮件的应用程序(pc可执行文件,而不是Web应用程序)编写Web API。
用户点击某个东西,应用程序就会与API通信,API会生成一封电子邮件并发送出去

我必须确保没有未经授权的人可以访问API,因此我需要进行某种身份验证,但我不知道如何正确执行

将有更多的应用程序访问API

第一个想法是发送用户名和密码,但这并不能真正解决问题。因为如果有人反编译应用程序,他们将拥有请求url和包括用户/密码在内的变量,或者只是可以嗅探它

所以。。。我有什么选择

我相当肯定安全连接(SSL)目前对我不可用,但这仍然不能帮助我解决反编译问题,对吗


编辑


起初我没有这样说,但是不会要求用户输入用户名/密码。必须进行身份验证的是应用程序,而不是应用程序的用户。

如果需要防止人们看到通过网络从应用程序发送到API的纯文本密码,则需要使用SSL


对于反编译问题,您希望在API中存储密码的哈希,而不是原始密码。请参见此处的说明:。

总有人能够反编译并查找变量。模糊处理程序可能能够更好地隐藏它们。嗅探在没有SSL的情况下也很容易,除非您使用私有和公共密钥集来加密请求数据客户端和解密服务器端(但显然,该密钥将存储在客户端应用程序中)

最好的办法是提供您认为需要的尽可能多的保护层,创建安全连接并混淆代码。您可以阅读以下文章,其中演示了不使用SSL的安全连接:


如前所述,您不应该以纯文本格式存储密码。当用户在应用程序中输入密码时,存储密码的散列。服务器上应存储相同的哈希。这样,如果拦截器看到散列,它们至少不会看到用户的原始密码。

我建议您查看OAuth。它肯定会帮助您通过授权工具访问API来解决安全问题


软件的分发确实是问题的症结所在。散列用户名和密码并将其存储在软件中并不比存储未散列的值更有用,因为两者都可以访问API服务器。如果要为用户实现用户名和密码,我认为可以将其用作API控件的前置游标,而无需将值存储在软件本身中。让我分两部分来描述这一点

请求签名

API请求验证最常用的方法是请求签名。基本上,在将请求发送到API服务器之前,会对请求中的参数进行排序,并向混合中添加一个唯一键。然后使用整个批生成一个哈希,并将其附加到请求中。例如:

public static function generateRequestString(array $params, $secretKey)
{
    $params['signature'] = self::generateSignature($params, $secretKey);
    return http_build_query($params,'','&');
}

public static function generateSignature($secretKey, array $params)
{
    $reqString = $secretKey;
    ksort($params);
    foreach($params as $k => $v)
    {
        $reqString .= $k . $v;
    }
    return md5($reqString);
}
您可以使用上面的代码创建一个API请求查询字符串,只需调用
generateRequestString()
方法,其中包含所有要发送的参数。密钥是唯一地提供给API的每个用户的东西。通常,您将用户id与签名一起传递给API服务器,API服务器使用您的id从本地数据库获取密钥,并以构建请求的相同方式验证请求。假设密钥和用户id是正确的,则该用户应该是唯一能够生成正确签名的用户。请注意,该密钥从未在API请求中传递

不幸的是,这要求每个用户都有一个唯一的密钥,这对于您的桌面应用程序来说是个问题。这就引出了第二步

时间键

因此,您不能随应用程序分发密钥,因为它可以被反编译,密钥将被释放。为了反其道而行之,你可以制作非常短命的钥匙

假设您已经实现了桌面应用程序的一部分,该部分要求用户输入用户名和密码,那么您可以让应用程序向您的服务器执行身份验证请求。成功进行身份验证后,您可以返回带有响应的临时密钥,桌面应用程序可以在授权会话的生命周期内存储该密钥,并用于API请求。因为您提到不能使用SSL,所以此初始身份验证是最易受攻击的部分,您必须接受一些限制

Andy E建议的文章是一个很好的方法(我投了赞成票)。这基本上是一次握手,以建立一个可用于身份验证的短期密钥。相同的密钥可用于签名哈希。您也可以冒险发送未加密的用户名/密码并获取临时密钥(这种情况只会发生一次),但您必须意识到它可能被嗅探到

摘要


如果您可以建立一个临时会话密钥,那么就不必在客户端程序中存储任何可以反编译的内容。向服务器发送一次用户名/密码就足以证明这一点。一旦您拥有该密钥,您就可以使用它在桌面应用程序中创建请求,并在API服务器上验证请求。

+1-尽管我有一条评论:
对用户名和密码进行哈希运算并将其存储在软件中并不比存储未哈希值更有用,因为任何一个都可以访问API服务器。虽然这与询问者无关