Web API HMAC 身份验证 - 间歇性 404 未找到响应
Web API HMAC Authentication- Intermittent 404 Not Found Response
我在部署在 Azure 上的 Web Api 应用程序中遵循 here 概述的 HMAC 身份验证方法,但我 运行 遇到 404 错误超过一半相同 HTTP GET 调用的时间。
似乎当我调用服务器时,即使我的请求 URI 是格式,
http://mywebapp.azurewebsites.net/api/foo/bar?val=123
大约一半时间,HttpResponseMessage 中的请求 URI 返回为
http://mywebapp.azurewebsites.net/Account/Login?ReturnUrl=%2Fapi%2Ffoo%2Fbar%3Fval%3D123
只有当我在我的 foo 控制器上应用 HMACAuthentication 属性时才会发生这种情况。
奇怪的是,它不是每次都发生,当我在本地主机上 运行 时也不会发生。我已经完全从 github 存储库中复制了示例。我在想服务器时间可能与此有关,但这并不能解释为什么请求有时会通过而其他请求会失败……它应该是一致的。也不确定代码的哪一部分与放在这里有关,所以请让我知道有什么帮助。
如果您对此有任何见解,我将不胜感激。提前致谢!
搞清楚了,问题出在 repo 中的 isReplayRequest 方法中。
这是原始方法定义:
private bool isReplayRequest(string nonce, string requestTimeStamp)
{
if (System.Runtime.Caching.MemoryCache.Default.Contains(nonce))
{
return true;
}
DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
TimeSpan currentTs = DateTime.UtcNow - epochStart;
var serverTotalSeconds = Convert.ToUInt64(currentTs.TotalSeconds);
var requestTotalSeconds = Convert.ToUInt64(requestTimeStamp);
if ((serverTotalSeconds - requestTotalSeconds) > requestMaxAgeInSeconds)
{
return true;
}
System.Runtime.Caching.MemoryCache.Default.Add(nonce, requestTimeStamp, DateTimeOffset.UtcNow.AddSeconds(requestMaxAgeInSeconds));
return false;
}
问题发生在第二个 if 条件下,其中 serverTotalSeconds 和 requestTotalSeconds 是 无符号整数。
在某些周期性情况下,时间戳最终会变为负数(即 requestTotalSeconds 比 serverTotalSeconds 大 1),最终会将 (serverTotalSeconds - requestTotalSeconds) 的值设置为 18446744073709551615,这是 UInt64 的最大值能hold住
在我的例子中,我使用了两个 TimeSpan 对象来比较时间并得出以秒为单位的差异。
希望这对其他人有帮助。
我在部署在 Azure 上的 Web Api 应用程序中遵循 here 概述的 HMAC 身份验证方法,但我 运行 遇到 404 错误超过一半相同 HTTP GET 调用的时间。
似乎当我调用服务器时,即使我的请求 URI 是格式,
http://mywebapp.azurewebsites.net/api/foo/bar?val=123
大约一半时间,HttpResponseMessage 中的请求 URI 返回为
http://mywebapp.azurewebsites.net/Account/Login?ReturnUrl=%2Fapi%2Ffoo%2Fbar%3Fval%3D123
只有当我在我的 foo 控制器上应用 HMACAuthentication 属性时才会发生这种情况。
奇怪的是,它不是每次都发生,当我在本地主机上 运行 时也不会发生。我已经完全从 github 存储库中复制了示例。我在想服务器时间可能与此有关,但这并不能解释为什么请求有时会通过而其他请求会失败……它应该是一致的。也不确定代码的哪一部分与放在这里有关,所以请让我知道有什么帮助。
如果您对此有任何见解,我将不胜感激。提前致谢!
搞清楚了,问题出在 repo 中的 isReplayRequest 方法中。
这是原始方法定义:
private bool isReplayRequest(string nonce, string requestTimeStamp)
{
if (System.Runtime.Caching.MemoryCache.Default.Contains(nonce))
{
return true;
}
DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc);
TimeSpan currentTs = DateTime.UtcNow - epochStart;
var serverTotalSeconds = Convert.ToUInt64(currentTs.TotalSeconds);
var requestTotalSeconds = Convert.ToUInt64(requestTimeStamp);
if ((serverTotalSeconds - requestTotalSeconds) > requestMaxAgeInSeconds)
{
return true;
}
System.Runtime.Caching.MemoryCache.Default.Add(nonce, requestTimeStamp, DateTimeOffset.UtcNow.AddSeconds(requestMaxAgeInSeconds));
return false;
}
问题发生在第二个 if 条件下,其中 serverTotalSeconds 和 requestTotalSeconds 是 无符号整数。
在某些周期性情况下,时间戳最终会变为负数(即 requestTotalSeconds 比 serverTotalSeconds 大 1),最终会将 (serverTotalSeconds - requestTotalSeconds) 的值设置为 18446744073709551615,这是 UInt64 的最大值能hold住
在我的例子中,我使用了两个 TimeSpan 对象来比较时间并得出以秒为单位的差异。
希望这对其他人有帮助。