所需的防伪 cookie“__RequestVerificationToken”不存在

Posted

技术标签:

【中文标题】所需的防伪 cookie“__RequestVerificationToken”不存在【英文标题】:The required anti-forgery cookie "__RequestVerificationToken" is not present 【发布时间】:2016-01-23 06:09:49 【问题描述】:

我的网站每天大约会出现 20 次此异常,通常表单可以正常工作,但在某些情况下会出现此问题,我不知道为什么如此随机。

这是 elmah 记录的异常

500 HttpAntiForgery The required anti-forgery cookie __RequestVerificationToken" 不存在。

但它发送令牌的形式如 elmah 在 XML 日志中显示的那样

<form>
    <item name="__RequestVerificationToken">
      <value string="DNbDMrzHmy37GPS6IFH-EmcIh4fJ2laezIrIEev5f4vOhsY9T7SkH9-1b7GPjm92CTFtb4dGqSe2SSYrlWSNEQG1MUlNyiLP1wtYli8bIh41"/>
    </item>
    <item name="toPhone">
      <value string="XXXXXX"/>
    </item>
    <item name="smsMessage">
      <value string="xxxxxxxx"/>
    </item>
</form>

这是我在控制器上使用数据属性检查令牌是否有效的方法

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<JsonResult> Send(SMSModel model)

    // my code goes here

这是我在视图中的表单

@using (html.BeginForm("Send", "SMS", FormMethod.Post, new  @class = "form-sms", autocomplete = "off" ))

    @Html.AntiForgeryToken()
    <div class="row">
        <div class="col-md-12">
            <div class="form-group">
                <div class="input-group">
                    <div class="input-group-addon">+53</div>
                    @Html.TextBoxFor(m => m.toPhone, new  @class = "form-control", placeholder = "teléfono", required = "required", type = "tel", maxlength = 8 )
                </div>
            </div>
        </div>
    </div>
    <div class="form-group" style="position:relative">
        <label class="sr-only" for="exampleInputEmail3">Message (up to 135 characters)</label>
        @Html.TextAreaFor(m => m.smsMessage, new  rows = 4, @class = "form-control", placeholder = "escriba aquí su mensaje", required = "required", maxlength = "135" )
        <span class="char-count">135</span>
    </div>
    if (ViewBag.Sent == true)
    
        <div class="alert alert-success alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <strong>Su mensaje ha sido enviado <span class="hidden-xs">satisfactoriamente</span></strong>
        </div>
    
    if (ViewBag.Error == true)
    
        <div class="alert alert-danger alert-dismissible" role="alert">
            <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <strong>Error:</strong> Por favor revise el número de teléfono.
        </div>
    
    <div class="errorToMany"></div>
    <button type="submit" class="btn btn-default btn-block">Enviar SMS</button>

这就是我使用 AJAX 发布数据的方式

$('form.form-sms').submit(function (event) 
    $.ajax(
        url: $(this).attr("action"),
        type: "POST",
        data: $(this).serializeArray(),
        beforeSend: function (xhr) 
            $('.btn-default').attr("disabled", true);
            $('.btn-default').html("Enviando...")
        ,
        success: function (data, textStatus, jqXHR) 
            if (data[0] == false && data[1] == "1") 
               some code 
             else 
               location.reload();
            
        ,
        error: function (jqXHR, textStatus, errorThrown)  
    );
    return false;
);

表单在大多数情况下运行良好,但此错误不断发生,我不知道为什么,我在 Stack Overflow 上检查了其他问题,但对我没有任何效果。

关于我如何发布数据的进一步说明。

此发送 SMS 的表单具有 ToNumber 和 Message 字段。当用户单击提交按钮时,AJAX 函数将获得控制权并将其发布为序列化​​表单的字段数据,当我在控制器中的函数完成并返回表明一切顺利的 JSON 结果时,AJAX 方法会重新加载向用户显示成功的页面消息。

任何可能导致此问题的想法。

【问题讨论】:

【参考方案1】:

听起来好像一切都在按预期进行。

防伪助手@Html.AntiForgeryToken() 的工作方式是在页面中注入一个名为__RequestVerificationToken 的隐藏表单字段,并在浏览器中设置一个cookie。

当表单被回发时,两者会进行比较,如果它们不匹配或 cookie 丢失,则会引发错误。

因此,Elmah 记录表单正在发送__RequestVerificationToken 并不重要。它总是会的,即使在CSRF 攻击的情况下,因为这只是隐藏的表单字段。

<input name="__RequestVerificationToken" type="hidden" value="DNbDMrzHmy37GPS6IFH-EmcIh4fJ2laezIrIEev5f4vOhsY9T7SkH9-1b7GPjm92CTFtb4dGqSe2SSYrlWSNEQG1MUlNyiLP1wtYli8bIh41" />

另一方面,错误消息说没有发送相应的COOKIE

500 HttpAntiForgery 所需的防伪cookie __RequestVerificationToken" 不存在。

所以基本上某人/某事正在重播表单帖子,而没有发出原始请求来获取 cookie。因此他们有隐藏的表单域 __RequestVerificationToken 但不是用于验证它的 cookie。

所以看起来事情正在按应有的方式进行。检查您的日志:IP 号码和引荐来源网址等。在重定向表单内容时,您可能受到攻击,或者可能正在做一些奇怪或错误的事情。如上所述,referrers 是处理此类错误的好地方,假设这不是被欺骗的。

另请注意,根据MDN

location.reload();

Location.reload() 方法从当前重新加载资源 网址。它的可选唯一参数是一个布尔值,当它是 true,导致页面总是从服务器重新加载。如果是 false 或未指定,浏览器可能会从其重新加载页面 缓存

如果是这样,有时会从缓存中加载,那么您最终可能会得到一个 POST,它具有旧页面令牌但没有 cookie。

那就试试吧:

location.reload(true);

【讨论】:

伙计,谢谢你的详细解释,我不知道 location.reload(true) 技巧。我刚刚更改了我的代码,将等到明天看看是否不再收到此问题,如果是这种情况,我会将您的答案标记为已接受。【参考方案2】:

最近遇到了类似的问题。 防伪cookie确实丢失了,所以(正如其他人指出的那样)

    服务器没有将 cookie 添加到请求中,或者 浏览器拒绝了它。

在我的情况下,它是服务器:我没有在本地环境中使用 SSL,但在 web.config 我有以下行:

<httpCookies requireSSL="True"/>

这种情况下的解决方案是切换到 SSL,或者将值设置为本地环境的“False”。

【讨论】:

在我们的例子中,我们在一些 SSL 和一些 不是 SSL 的 localhost 项目之间切换时遇到了问题 我的 XML 验证器抱怨 True,为了保持沉默,使用小写:true【参考方案3】:

除了 rism 的出色回答之外,遇到此错误的另一个可能原因是您的浏览器或浏览器插件阻止设置 cookie

【讨论】:

【参考方案4】:

我在边缘浏览器中遇到了同样的问题。

我已经通过更改浏览器设置解决了这个问题。

按照说明解决问题:

转到设置 > 查看高级设置 > Cookies > 更改为“不阻止 Cookie”。

关闭浏览器并检查。

我想,这可能会对某人有所帮助。

【讨论】:

【参考方案5】:

检查你是否错过了前端@Html.AntiForgeryToken() 中的这一行

【讨论】:

【参考方案6】:

可能想看看这个问题。 The anti-forgery cookie token and form field token do not match in MVC 4

这可能是超时问题。基本上,当超时发生时,cookie 不会被存储,因为运行该站点的 iis 用户没有正确的访问权限。对我来说,我更改了应用程序池以加载用户配置文件,这似乎解决了它。

【讨论】:

【参考方案7】:

就我而言,它与 IIS 上的缓存有关。 我不得不在服务器管理器中重新启动整个 IIS 服务器。

【讨论】:

【参考方案8】:

将@Html.AntiForgeryToken() 放入表单中

【讨论】:

以上是关于所需的防伪 cookie“__RequestVerificationToken”不存在的主要内容,如果未能解决你的问题,请参考以下文章

所需的防伪表单字段“__RequestVerificationToken”不存在 用户注册错误

所需的防伪表单字段“__RequestVerificationToken”不存在

所需的防伪表单字段 __requestverificationtoken 不存在 ajax 调用时出错

ajax 调用中不存在所需的防伪表单字段“__RequestVerificationToken”

从 ajax 方法调用操作引发错误:所需的防伪表单字段“__RequestVerificationToken”不存在

jmeter中的相关问题:所需的防伪形式字段“__RequestVerificationToken”不存在