我今天花了一些时间查看 C# 中的各种 HMAC 实现,以了解即将推出的 WebAPI 项目。我想从一些现有的代码开始,只是为了在我从头开始编写它或根据我的需要修改它之前更好地了解它。
这里和网络上都有很多很棒的文章和帖子。但是,我已经到了需要一些指示的地步,并且非常感谢一些见解。
我从 Cuong 的帖子开始:如何保护 ASP.NET Web API。
我知道我必须扩展它,因为我想同时支持 json 和 formencoded 数据。我的测试客户端也是使用 HttpClient 用 C# 编写的,我创建了一个空的 WebAPI 项目并使用 ValuesController。
以下是我的观察和问题:
发布:为了让 Cuong 的代码正常工作(验证成功),我的 POST 需要在 URL 中包含参数,但是为了将值发送到我的控制器,我需要将它们包含在正文中。这对于这种类型的身份验证是否正常?在这个特定的例子中,我正在散列的消息是 http://:10300/api/values?param1=value1¶m2=value2。现在我可以手动解析查询字符串以获取它们,但是为了通过绑定将值获取到我的控制器,我还必须:
var dict = new Dictionary<string, string> { {"param1", "value1"}, {"param2", "value2"} }; var content = new FormUrlEncodedContent(dict); var response = await httpClient.PostAsync(httpClient.BaseAddress, content);
否则,我的参数在 ValuesController 的发布操作中始终为空。
我计划扩展代码以包含随机数。在随机数、时间戳和动词的组合之间,对于安全散列来说足够了吗?真的需要散列消息吗?
我尝试(非常不成功)扩展代码以支持 json 以及形成编码数据,但我一定遗漏了一些明显的东西。
Cuong 使用 Authentication 和 Timestamp 标头,而不是将签名和时间戳放在查询字符串中。一种方法比另一种方法有好处吗?我读过的大多数文章都在查询字符串本身中包含它们。
代码看起来很棒,我在这里有点不合时宜。我可能更安全(更理智?)只是从头开始写它以欣赏它的细微差别。也就是说,如果有人可以对我所看到的内容有所了解,那就太好了。
归根结底,我希望能够使用 WebAPI 框架的内置授权机制来简单地为方法/控制器赋予属性,能够接受表单编码和 json 数据,并为复杂类型合理地模型绑定。
* 更新 *
我今天做了更多的工作,下面是我的 nUnit PostTest 中的代码。我想出了如何在不将它们包含在正文和查询字符串中的情况下获取值(下面的代码)。
[Test]
public async void PostTest()
{
using (var httpClient = new HttpClient())
{
var payload = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"key1", "value1"},
{"key2", "value2"}
});
var now = DateTime.UtcNow.ToString("U");
httpClient.BaseAddress = new Uri(string.Format("http://ipv4.fiddler:10300/api/values"));
httpClient.DefaultRequestHeaders.Add("Timestamp", now);
httpClient.DefaultRequestHeaders.Add("Authentication", string.Format("test:{0}", BuildPostMessage(now, httpClient.BaseAddress, await payload.ReadAsStringAsync())));
var response = await httpClient.PostAsync(httpClient.BaseAddress, payload);
await response.Content.ReadAsStringAsync();
Assert.AreEqual(true, response.IsSuccessStatusCode);
}
}
我还弄清楚了它的模型绑定部分。这里有一篇很棒的文章:http ://www.west-wind.com/weblog/posts/2012/Mar/21/ASPNET-Web-API-and-Simple-Value-Parameters-from-POSTed-data解释了POST 是如何工作的,我能够让它与我自己设计的模型以及 FormDataCollection 对象一起工作。
现在我想知道是否值得添加 json 编码的消息,或者标准化 FormUrlEncoding 是否是要走的路。此外,客户端通知是否足够,或者我应该实现服务器端通知?服务器端通知是否将所有对服务的调用加倍(第一个抛出 401,第二个包含带有通知的有效负载?