C# MVC-防伪令牌错误

C# MVC-防伪令牌错误,c#,asp.net-mvc,C#,Asp.net Mvc,我被带到了我的第一个MVC和C项目中,所以我感谢任何指导 我创建了一个新功能,检查用户登录时是否接受过安全培训。如果没有,用户将被引导到一个培训页面,在那里他们只是同意/不同意规则。如果用户同意,则登录完成。如果用户不同意,他/她将注销 我遇到的问题是,当我在“培训”视图中选择“同意/不同意”按钮时,我会得到以下结果 它应该将我路由到主页或注销用户 控制器 看法 我认为您没有提供足够的代码来正确诊断此特定错误。通常,此防伪例外情况是由于身份验证状态的更改造成的。当您在页面上调用@Html.Ant

我被带到了我的第一个MVC和C项目中,所以我感谢任何指导

我创建了一个新功能,检查用户登录时是否接受过安全培训。如果没有,用户将被引导到一个培训页面,在那里他们只是同意/不同意规则。如果用户同意,则登录完成。如果用户不同意,他/她将注销

我遇到的问题是,当我在“培训”视图中选择“同意/不同意”按钮时,我会得到以下结果 它应该将我路由到主页或注销用户

控制器

看法


我认为您没有提供足够的代码来正确诊断此特定错误。通常,此防伪例外情况是由于身份验证状态的更改造成的。当您在页面上调用@Html.AntiForgeryToken时,响应中也会使用该令牌设置cookie。重要的是,如果用户经过身份验证,那么用户的身份将用于组成该令牌。然后,如果该用户的身份验证状态在设置cookie和将表单发布到验证该令牌的操作之间发生更改,则该令牌将不再匹配。这可以是用户在设置cookie后进行身份验证,也可以是用户在设置cookie后注销。换句话说,如果用户在页面加载时是匿名的,但在提交表单之前登录,那么它仍然会失败

再一次,我在这里没有看到任何明显会导致这种情况的代码,但是我们也没有关于用户如何登录到一个take to this view的完整图片

也就是说,有一些非常明显的错误可能会导致或可能不会导致这一特定问题,但肯定会在某个时候导致问题。首先,按钮没有名称属性。根据您的操作代码,您似乎认为id属性将是FormCollection中显示的属性,但事实并非如此。您需要将name=accept和name=reject分别添加到按钮中,以使当前代码正常工作

其次,在用户成功接受时,应该重定向到加载SecurityTrainingSuccess视图的操作,而不是直接返回该视图。这部分是PRG Post Redirect Get模式的一部分,确保提交不会被重播。任何和所有post操作都应在成功时重定向

第三,至少是开箱即用,注销将是一个post操作,这意味着您不能重定向到它。重定向总是通过GET实现的。从技术上讲,您可以让注销响应GET和POST,或者代替POST,但这是一种反模式。原子操作应始终通过POST或更合适的动词(如PUT、DELETE等)来处理,但决不能使用GET

最后,尽管FormCollection很小,但一般不鼓励使用它。对于这样一个简单的表单,您可以直接将您的帖子绑定为params:

public ActionResult UserSecurityTrainingConfirm(string accept, string reject, ...)
但是,引入一个布尔值可能更符合逻辑,也更简单,如:

public ActionResult UserSecurityTrainingConfirm(bool accepted, ...)
然后,您的按钮可以是:

    <button type="submit" name="accepted" value="true" class="btn btn-default">Accept</button>
    <button type="submit" name="accepted" value="false" class="btn btn-default">Reject</button>

这基本上使它们像收音机一样。单击的参数提交其值,因此接受的参数将相应地为true或false。另外,请注意,我将您切换到了真正的按钮元素。对按钮使用输入是一种不好的做法,尤其是当您实际需要它来提交值时,因为值和显示本质上是绑定在一起的。有了button元素,您可以发布您想要的任何内容,并且仍然可以独立地将其标记为您想要的任何文本。

您实际上应该只从HTTP post控制器操作方法返回RedirectToAction,除非您返回的是无效的模型。例如,此行返回ViewSecurityTrainingSuccess;应将此行返回重定向到ActionSecurityTrainingSuccess;为了保持正确的PRG Post、重定向、获取模式。MVC很大程度上依赖于你是否正确地遵循PRG,否则事情就会变得很糟糕。
public ActionResult UserSecurityTrainingConfirm(bool accepted, ...)
    <button type="submit" name="accepted" value="true" class="btn btn-default">Accept</button>
    <button type="submit" name="accepted" value="false" class="btn btn-default">Reject</button>