我在两条腿OAuth的前提下构建自己的网络服务。
每个经过身份验证的请求都会包含一个HMAC。
我知道可以这样做:
public ActionResult userInfoExample(string HMAC, string username)
{
MyMembership.checkHMAC(HMAC);
//get user
return View();
}
但这是相当讨厌的,因为HMAC需要包含在每个动作的参数中。它的弱类型和废话。
我想做这样的事情:
[AuthorizeHMAC]
public ActionResult userInfoExample(string username)
{
//get user
return View();
}
I found this,它提到我应该查看自定义模态文件夹,然后I found this,在阅读之后我不确定如何才能完成这项工作。
我的目标是使用HMAC进行身份验证(/授权)(我假设)放在URL参数中,即:http://www.website.com/foo/bar?username=xxx&hmac=xxxxxxxxx < / p>
我想知道是否有人有任何我可以阅读或直接解决的参考资料 我也欢迎批评我对API安全的基本理解,或者我是如何做事的,我对这个领域还是比较陌生的
答案 0 :(得分:1)
查看我的代码 http://mvcsecurity.codeplex.com/
我做类似的事情来验证页面上的参数(虽然它不是HMAC)。由于您将在View Im上生成它(或将其传递给视图),您可以使用与我在属性中检查它的方式相同的方式检查它。
自:
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//The hidden form field that contains our hash - for ex. CustomerId is rendered as a hidden input id="_CustomerIdToken"
string encryptedPropertyName = string.Format("_{0}Token", _propertyName);
//grab the token
string hashToken = filterContext.HttpContext.Request.Form[encryptedPropertyName];
//The encrypted form data MUST be there. We do not allow empty strings otherwise this could give
//an attack vector in our filter as a means to bypass checks by simply passing in an empty validation token.
if (string.IsNullOrEmpty(hashToken))
{
throw new MissingFieldException(string.Format("The hidden form field named value {0} was missing. This is created by the Html.AntiModelInjection methods. Ensure the name used on your [ValidateAntiModelInjectionAttribute(\"!HERE!\")] matches the field name used in Html.AntiModelInjection method. If this attribute is used on a controller method that is meant for HttpGet, then the form value would not yet exist. This attribute is meant to be used on controller methods accessed via HttpPost.", encryptedPropertyName));
}
//Get the plain text value
string formValue = filterContext.HttpContext.Request.Form[_propertyName];
//Plain text must be available to compare.
if (string.IsNullOrEmpty(formValue))
{
throw new MissingFieldException(string.Format("The form value {0} was missing. If this attribute is used on a controller method that is meant for HttpGet, then the form value would not yet exist. This attribute is meant to be used on controller methods accessed via HttpPost.", _propertyName));
}
//We cannot encrypt the form value and compare to the previously encrypted form token.
//Each time you Encrypt() with the MachineKey class even using the same plain text, the end result is difference.
byte[] plainTextBytes = MachineKey.Decode(hashToken, MachineKeyProtection.Encryption);
string plainText = Encoding.Unicode.GetString(plainTextBytes);
//And compare
if (string.Compare(plainText, formValue , false, CultureInfo.InvariantCulture) != 0)
{
throw new HttpAntiModelInjectionException(string.Format("Failed security validation for {0}. It is possible the data was tampered with as the original value used to create the form field does not match the current property value for this field. Ensure if this is a web farm, the machine keys are the same.",_propertyName));
}
filterContext.HttpContext.Trace.Write("(Logging Filter)Action Executing: " +
filterContext.ActionDescriptor.ActionName);
base.OnActionExecuting(filterContext);
}