在 MVC3 中对 HMAC 进行身份验证



我在 2 条腿 OAuth 的前提下构建自己的 Web 服务。

对于每个经过身份验证的请求,将包含一个包含的 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();
    }
我找到了这个,

它提到我应该看看自定义模态活页夹,所以后来我找到了这个,阅读后我不确定我该如何做到这一点。

的目标是使用(我假设)放置在 URL 参数中的 HMAC 进行身份验证(/授权),即:http://www.website.com/foo/bar?username=xxx&hmac=xxxxxxxxx

我想知道是否有人有任何我可以阅读的参考资料或直接解决方案。
我也欢迎批评我对 API 安全的基本理解,或者我是如何做事的,我对这个领域相当陌生

查看我的代码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);
        }

相关内容

  • 没有找到相关文章

最新更新