2

我在这里阅读了很多关于使用 api 密钥、令牌、hmac 等保护 web api 的问题,但还没有找到我正在寻找的答案。

我正在开发一个包含 Internet 和 Intranet 站点、Web api 和 Android/iOS 应用程序的 MVC4 Web 应用程序项目。

Web API 将由我的应用程序使用,其他任何人都不会使用它,因为它将访问敏感数据

保护这个 api 的最佳方法是什么,只有我的应用程序可以使用它?看起来如此简单的请求是非常难以开始的。

我已经使用 HMAC 和其他一些人查看了关于 SO 的帖子,但它们听起来都不适合这里,很可能我只是错过了一些东西。

HMAC 是要走的路还是客户端证书更适合这种情况?

我应该使用 SSL 和某种 API 密钥吗?

我知道这个问题有点含糊,我已经盯着它看了一个多小时,试图弄清楚我在想什么,所以我想我会发布它并在需要时更新...... :(

我很乐意应要求提供更多详细信息。

4

4 回答 4

3

为您的每个应用程序生成一个密钥,并让它们在每个请求中将密钥作为令牌传递。然后,您的服务器可以验证密钥并验证请求。

查看 ASP.NET 站点中的基本身份验证模块。该示例使用“基本”作为授权方案,但您可以改用“令牌”来更改它。

private static void OnApplicationAuthenticateRequest(object sender, EventArgs e)
    {
        var request = HttpContext.Current.Request;
        var authHeader = request.Headers["Authorization"];
        if (authHeader != null)
        {
            var authHeaderVal = AuthenticationHeaderValue.Parse(authHeader);

            // RFC 2617 sec 1.2, "scheme" name is case-insensitive
            if (authHeaderVal.Scheme.Equals("token",
                    StringComparison.OrdinalIgnoreCase) &&
                authHeaderVal.Parameter != null)
            {
                AuthenticateUser(authHeaderVal.Parameter);
            }
        }
    }

有了基本身份验证模块后,您可以简单地使用 Authorize 属性装饰任何操作或控制器,它将请求转发到基本身份验证处理程序。

namespace webapi.Controllers
{
     [Authorize]
     public class SensitiveDataController : ApiController
     {
       ...
     }
}

就网络而言,在使用基本身份验证时必须使用 SSL,因为您的密钥将以纯文本形式传输。

于 2013-06-19T21:27:10.567 回答
2

您可以使用 FormsAuthentication。加密票证并确保两个配置文件中的 machineKey 相同。看到这个这个。这将允许在 Web 应用程序和 api 之间共享相同的用户凭据。在这种情况下,ASP.NET FAM 模块将建立身份。

对于 api 密钥,请查看hawk scheme。它使用共享对称密钥。但是,Hawk 功能齐全,在达到 1.0 版之前,它可能会发生变化。尽管如此,它将为您提供实现基于 HMAC 的安全性的好主意。我在这里为 Hawk 提供了一个 .NET 实现。巴勃罗也有一个。在这种情况下,您需要编写一个消息处理程序来建立消费应用程序的身份。

于 2013-06-21T03:27:47.673 回答
2

在高流量应用程序的一般情况下,上述所有答案都有一个许多攻击者可以轻松利用的缺陷:使用越狱的 iPhone,您可以破坏 SSL - 不是针对您的服务器,而是当他们在手机上安装您的应用程序时,他们至少可以分析您发送的包裹。

避免这种情况的最好方法(在我看来)是使用“准时密码”——实时密码。

您如何生成这些一次性密码?

A1。为每个设备获取一个device_identifier(这也可以是任何随机数,但您应该避免与其他设备的标识符冲突)

A2。有一个api_key, 您将用于散列

现在,如果您想将包发送到您的 api,请执行以下操作:

B1。构建你的普通包,这里是一些 json 有效负载的例子:

var payload = {"hello":"world"}

B2。var hashed_payload = hash(payload)使用您最喜欢的散列函数散列您的

B3。为此包生成一次性密码:

var otp = hash(salt & hashed_payload & device_token & api_key)

现在您拥有了发送到服务器所需的一切:

在标题中,您还需要发送otp,saltdevice_token

在服务器上,您将执行标记为的相同步骤B1-3,并将您的哈希结果与客户端提供的结果进行比较。之后,您必须确保为此“禁止”此salt操作,device_token以避免重放攻击。

这种方法仍然存在一个缺陷,但需要攻击者做更多工作:他们可以api_key在您编译的代码中找到您的代码。

于 2015-05-08T12:21:07.167 回答
1

我正在做一个类似的项目,我为每个访问我的 API 的用户或客户端应用程序分配唯一的 API 密钥。我不是安全专家,但我建议您使用 SSL 并为您的 Android 和 iOS 应用程序生成唯一的 API 密钥。使用 SSL,传输到您的 API 的数据将被加密和保护。

于 2013-06-19T20:34:50.400 回答