我被要求为一个允许发送电子邮件的应用程序(pc可执行程序,而不是Web应用程序)编写一个web。
用户点击某个东西,应用程序与API进行通信,API生成电子邮件并将其发送出去。
我必须确保没有任何未经授权的人能够访问API,所以我需要进行某种身份验证,而且我不知道如何正确地进行验证。
将会有更多的应用程序访问API。
首先想到的是-发送用户名和密码,但这并不能真正解决问题。因为如果有人解压缩应用程序,他们将拥有请求url和变量(包括用户/密码),或者只需嗅探它即可。
所以..。我有什么选择?
我确信目前我还没有安全连接(SSL),但这不会帮助我解决反编译问题,对吗?
编辑
我一开始没有这么说,但是用户不会被问到用户名/密码。必须进行身份验证的是应用程序,而不是应用程序的用户。
发布于 2010-01-14 18:27:25
我建议你去看看OAuth。它肯定会帮助您解决访问API的授权工具的安全性问题。
http://oauth.net
发布于 2010-01-15 00:36:57
软件的分发是问题的症结所在。散列用户名和密码并将它们存储在软件中并不比存储未散列的值更有用,因为这两种方法都可以访问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,所以初始身份验证是中最脆弱的部分,您必须忍受一些限制。
安迪·E提出的这篇文章是一个很好的方法(我投了赞成票)。这基本上是一个握手,以建立一个短期的密钥,可以用来认证。相同的密钥可用于签名散列。您也可以抓住机会,只需发送未加密的用户名/密码,并获得一个时态密钥(只会发生一次),但您必须意识到它可能会被监听。
摘要
如果您可以建立一个临时会话密钥,您就不必在客户端程序中存储任何可以解压缩的内容。发送给服务器一次的用户名/密码就足以证明这一点了。拥有该密钥后,您可以使用它在桌面应用程序中创建请求,并在API服务器上验证请求。
发布于 2010-01-14 17:49:56
有些人总是能够分解和寻找变量。混混者也许能把他们藏得更好一点。没有SSL,嗅探也很容易,除非您使用私有和公共密钥集加密请求数据客户端和解密服务器端(但很明显,此密钥将存储在客户端应用程序中)。
最好的做法是提供您认为需要的尽可能多的保护层,创建一个安全的连接并混淆您的代码。您可以查看以下文章,它演示了不使用SSL的安全连接:
http://www.codeproject.com/KB/security/SecureStream.aspx
正如mattjames所提到的,您不应该以纯文本格式存储密码。当用户向应用程序输入密码时,存储密码的散列。应该将相同的散列存储在服务器上。这样,如果哈希被拦截器看到,他们至少不会看到用户的原始密码。
https://stackoverflow.com/questions/2066107
复制相似问题