【问题标题】:The required anti-forgery form field "__RequestVerificationToken" is not present. AngularJs MVC所需的防伪表单字段“__RequestVerificationToken”不存在。 AngularJs MVC
【发布时间】:2016-03-24 09:08:25
【问题描述】:

我无法使用 AngularJs 将 RequestVerificationToken 从网页传递到服务器。

我的 AngularJs 代码是:

var app = angular.module('validation', []);
app.controller('SignUpController', function ($scope, $http) {
    $scope.model = {};
    $scope.email = {};
    $scope.sendEmail = function () {
        $http({
            method: 'POST',
            url: '/Contact/Test',
            data: $scope.email,
            headers: {
                'RequestVerificationToken': $scope.antiForgeryToken
            }
        }).success();
    };
});

自定义属性代码:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class CustomAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
    {


        private void ValidateRequestHeader(HttpRequestBase request)
        {
            string cookieToken = String.Empty;
            string formToken = String.Empty;
            string tokenValue = request.Headers["RequestVerificationToken"];
            if (!String.IsNullOrEmpty(tokenValue))
            {
                string[] tokens = tokenValue.Split(':');
                if (tokens.Length == 2)
                {
                    cookieToken = tokens[0].Trim();
                    formToken = tokens[1].Trim();
                }
            }
            AntiForgery.Validate(cookieToken, formToken);
        }

        public void OnAuthorization(AuthorizationContext filterContext)
        {

            try
            {
                if (filterContext.HttpContext.Request.IsAjaxRequest())
                {
                    ValidateRequestHeader(filterContext.HttpContext.Request);
                }
                else
                {
                    AntiForgery.Validate();
                }
            }
            catch (HttpAntiForgeryException e)
            {
                throw new HttpAntiForgeryException("Anti forgery token cookie not found");
            }
        }
    }

形式是:

@functions{
    public string GetAntiForgeryToken()
    {
        string cookieToken, formToken;
        AntiForgery.GetTokens(null, out cookieToken, out formToken);
        return cookieToken + ":" + formToken;
    }
}
<div ng-app="validation" ng-controller="SignUpController">
    <form role="form" id="frmContact" action="@Url.Action("Index", "Contact")" method="POST">
        <input id="antiForgeryToken" ng-model="antiForgeryToken" type="hidden" ng-init="antiForgeryToken='@GetAntiForgeryToken()'" />
        <fieldset class="form-group">
            @Html.LabelFor(x => x.EmailTitle)
            @Html.TextBoxFor(x => x.EmailTitle, new { placeholder = @Resource.EmailTitle, @class = "form-control", data_ng_model = "new.email.title" })
        </fieldset>
        <fieldset class="form-group">
            @Html.LabelFor(x => x.EmailAddress)
            @Html.TextBoxFor(x => x.EmailAddress, new { placeholder = @Resource.EmailAddress, @class = "form-control", data_ng_model = "new.email.address" })
        </fieldset>
        <fieldset class="form-group">
            @Html.LabelFor(x => x.EmailMessage)
            @Html.TextAreaFor(x => x.EmailMessage, new { placeholder = @Resource.EmailMessage, @class = "form-control", data_ng_model = "new.email.message" })
        </fieldset>


        <div>
            <button type="submit" name="btnEmailForm" id="btnEmailForm" class="btnLogin" ng-click="sendEmail()" value="sendMessage">@Resource.ContactFormSendMessageButton</button>
        </div>
        <div id="errorMessages" class="error">{{message}}</div>
    </form>
</div>

我已阅读以下帖子,但似乎无法解决问题,并且还从 https://github.com/techbrij/angularjs-asp-net-mvc 获取了在该示例中有效但在我的 MVC 应用程序中无效的代码:

http://techbrij.com/angularjs-antiforgerytoken-asp-net-mvc

https://parthivpandya.wordpress.com/2013/11/25/angularjs-and-antiforgerytoken-in-asp-net-mvc/

AngularJS Web Api AntiForgeryToken CSRF

http://bartwullems.blogspot.co.uk/2014/10/angularjs-and-aspnet-mvc-isajaxrequest.html

Where exactly to put the antiforgeryToken

http://www.ojdevelops.com/2016/01/using-antiforgerytokens-in-aspnet-mvc.html

谁能帮忙解决这个问题

【问题讨论】:

  • 不清楚:在 btnEmailForm 上单击您想将表单发送到 Index/Contact 并同时向 /Contact/Test 执行发布请求?还有您的自定义属性:CustomAntiForgeryTokenAttribute 它应用了哪些操作?而且 antiForgeryToken 输入没有属性 name= '__RequestVerificationToken' 这就是为什么它不去服务器。
  • 我的错误,因为无法解决这个问题而感到沮丧索引/联系人应该是 /Contact/Test

标签: c# angularjs asp.net-mvc-4


【解决方案1】:

在这种情况下,您执行submit$scope.sendEmail 形式的操作,它们可能会相互冲突,为了防止这种行为,您可以使用ng-submit 指令。并添加属性:name= '__RequestVerificationToken'ng-value="antiForgeryToken" 到对应的input

【讨论】:

    【解决方案2】:

    重要提示:[ValidateAntiForgeryToken] 的默认行为在表单值中需要 __RequestVerificationToken 标记。要以表单值格式向服务器发送请求,需要将content-type 设置为application/x-www-form-urlencoded。但不幸的是我没有这个选项,我的内容类型是application/json。因此我选择了这条自定义路径。

    让我解释一下我采取的有效方法。

    第一步:在你的视图(.cshtml)中声明@Html.AntiForgeryToken(),如下所示:

    <form id="inputForm" name="inputForm" ng-submit="submit(broker)" novalidate>
            @Html.AntiForgeryToken()
            /* other controls of form */
    </form>
    

    第 2 步:@Html.AntiForgeryToken() 将呈现一个隐藏字段,该字段将保存令牌值:

    <input name="__RequestVerificationToken" type="hidden" value="GvTcz2tTgHOS2KK_7jpHvPWEJPcbJmHIpSAlxY1">
    

    第 3 步:为防伪令牌验证创建自定义属性

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]    
    public class HbValidateAntiForgeryToken : FilterAttribute, IAuthorizationFilter, IExceptionFilter    
    {    
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            try
            {
                var antiForgeryCookie = filterContext.HttpContext.Request.Cookies[AntiForgeryConfig.CookieName];
                AntiForgery.Validate(antiForgeryCookie != null ? antiForgeryCookie.Value : null,
                    filterContext.HttpContext.Request.Headers["__RequestVerificationToken"]);                
            }
            catch (Exception ex)
            {                
                throw new SecurityException("Unauthorised access detected and blocked");
            }
        }
    
        public void OnException(ExceptionContext filterContext)
        {
            if (filterContext.Exception != null &&
                filterContext.Exception is System.Security.SecurityException)
            {
                filterContext.Result = new HttpUnauthorizedResult();
                // Handle error page scenario here
            }
        }
    }
    

    第 4 步:在需要的地方声明上述属性(仅在控制器的 HttpPost 方法上。不要在 HttpGet 上声明)

    [HttpPost]
    [HbValidateAntiForgeryToken]
    public JsonResult IsUsernameExists(string username)
    {
    }
    

    第 5 步:在 AngularJS 中,在工厂传递 __RequestVerificationToken 作为标题。

    hbServices.factory('RegistrationService', ['$resource',
    function ($resource) {
        return $resource(applicationPath + 'api/MyUserMembership/:dest', {}, {
            createNewUser: { method: 'POST', isArray: false, params: { dest: 'CreateNewUser' }, 
                             headers: { 
                                 '__RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
                                }
                            },
            isUsernameExists: { method: 'POST', isArray: false, params: { dest: 'IsUsernameExists' }, 
            headers: { 
                '__RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val()
               }
           }
        });
    }]);
    

    请注意我传递 __RequestVerificationToken 值的方式,该值是从 ASP.NET MVC 的 @Html.AntiForgeryToken() 呈现的隐藏字段中读取的。

    我的应用程序正在使用 jquery,并且已经引用了 jquery,因此读取值很容易。您可以尝试其他方法读取该值

    总结 AntiForgery.Validate() 在这里可以验证伪造令牌的价值,到目前为止非常棒。希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2017-12-26
      • 2016-09-10
      • 1970-01-01
      • 2014-07-13
      • 2016-05-26
      • 2016-03-27
      • 2018-04-25
      • 2015-03-14
      相关资源
      最近更新 更多