带有 ViewModel 和两个表单的页面上的“防伪 cookie 令牌和表单字段令牌不匹配”

Posted

技术标签:

【中文标题】带有 ViewModel 和两个表单的页面上的“防伪 cookie 令牌和表单字段令牌不匹配”【英文标题】:"The anti-forgery cookie token and form field token do not match" on page with ViewModel and two forms 【发布时间】:2015-06-17 23:20:25 【问题描述】:

在 Mono 上运行的 MVC4 应用程序中出现错误:

防伪cookie令牌和表单字段令牌不匹配

在“登录和注册”页面上。此页面有一个LoginOrRegisterViewModel,如下所示:

public class LoginOrRegisterViewModel

    public LoginModel Login  get; set; 
    public RegisterModel Register  get; set; 

通过 GET 请求传递到页面。

页面上有两个html.BeginForms(),一个Login-form 和一个Register-form。第一个调用控制器上的Login 操作,第二个调用Register 操作。这两个操作都有一个ValidateAntiForgeryToken 属性。提交表单时,分别从LoginOrRegisterViewModel 获取LoginRegister

当页面加载并且注册用户在一段时间(几个小时?)后尝试登录时,最初显示“登录和注册”页面,但是当提交Login 表单时,上面的错误会一直显示到根页面已刷新。

我在 Web.config 中包含了一个机器密钥,并在两个表单中都添加了 Html.AntiForgeryToken()。我怀疑这个错误可能与两个表单和视图模型有关。

有谁知道如何解决这个错误?谢谢。

【问题讨论】:

您是否同时使用 Code First 重新播种数据库而忘记将其关闭或其他什么?这是在数据库中重新创建用户的典型情况,从而导致防伪令牌有所不同。 @WimOmbelets 否,数据库未重新植入。只有在注册用户时才创建(显然)。 调用者会话在这几个小时内是否过期? AFAIK 这些令牌存储在会话中... :) @dna 这有关系吗?这些类型的应用程序错误不利于用户体验。现在我刚刚删除了防伪令牌。 好吧,如果会话过期(其中包含防伪令牌),那么当用户在此之后发布表单时,令牌的验证显然会失败。我并不是说这是您错误的原因,但它可能值得研究。 【参考方案1】:

MVC 最佳编码标准,始终以代码关注点分离的方式进行实践。

创建两个不同的模型 1 用于 LoginViewModel 和 2 用于注册视图模型。 通过 Partial 或 RenderAction 关键字为登录和注册和访问创建单独的局部视图。

如果您将 @Html.AntiForgeryToken() 放在您的 html 表单上,那么您需要通过编写属性 [ValidateAntiForgeryToken()] 在控制器端方法上验证反伪造 .

Html 助手将在您的表单中生成唯一标记,例如,

<input name="__RequestVerificationToken" type="hidden" value="4dvPVQIvpXNEKZyV1DCjeN1rmtMDJ9fQ2">

将为每个表单生成唯一的防伪令牌,并解决您的冲突。

如果您仍然面临困难,请告诉我。

【讨论】:

以上是关于带有 ViewModel 和两个表单的页面上的“防伪 cookie 令牌和表单字段令牌不匹配”的主要内容,如果未能解决你的问题,请参考以下文章

如何将相同的viewmodel设置为xamarin表单中的新mvvm中的两个视图

如何将流从 ViewModel 发送到 XAML 页面上的 MediaElement?

Knockout.js:页面或页面的一部分上的多个 ViewModel 绑定

使用viewmodel并将查询传递到同一视图

如何同时为单个表单上的两个不同控件设置两种不同的文化?

Struts2系列:(13)防表单重复提交(token + 拦截器)