在这里,我有两个表单帖子的简单 MVC3 应用程序。为了保护 CSRF 攻击,我根据 guidance here 以两种形式使用了 antiforgerytoken html 助手。 .
这是我的两个模型:
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
}
这是我的 homeController.cs:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index(User user)
{
if (ModelState.IsValid)
return RedirectToAction("About");
return View();
}
public ActionResult About()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult About(Employee employee)
{
if (ModelState.IsValid)
return RedirectToAction("PageA");
return View();
}
}
这是我的 Inex.cshtml:
@model MvcAntiforgeryToken.Models.User
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
<div>
<fieldset>
<legend>User Information</legend>
<div class="editor-label">
@Html.LabelFor(m => m.FirstName)
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.FirstName)
@Html.ValidationMessageFor(m => m.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(m => m.LastName)
</div>
<div class="editor-field">
@Html.PasswordFor(m => m.LastName)
@Html.ValidationMessageFor(m => m.LastName)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</div>
}
这是我的 About.cshtml:
@model MvcAntiforgeryToken.Models.Employee
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
<div>
<fieldset>
<legend>Employee Information</legend>
<div class="editor-label">
@Html.LabelFor(m => m.Id)
</div>
<div class="editor-field">
@Html.TextBoxFor(m => m.Id)
@Html.ValidationMessageFor(m => m.Id)
</div>
<div class="editor-label">
@Html.LabelFor(m => m.Name)
</div>
<div class="editor-field">
@Html.PasswordFor(m => m.Name)
@Html.ValidationMessageFor(m => m.Name)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
</div>
}
主页/索引的发布:
when user visits Home/Index, application created " RequestVerificationToken_Lw "cookie with value "pG2/E00Q2DngYxs98f92x9qqrIvrh6zCT/+GGte67NFZLazKFlz++QqMSHpkZ08Qum9vsBCtq7O7MSzCawJkEa2/hdjrWoAcHlDWxxYRWKXm+OxPbqlRs609zam4fK7hReGEX3zf8YR4ltH3oYf4AZgt2mZV31ihRGShiZ7Oy9k="
并遵循隐藏的表单输入
<input name="__RequestVerificationToken" type="hidden" value="B1KKzYEFEdINnuhy53MqqxHCHELPUd5pX3vRqYWz1+pkhBA6YGFvSVtXgSURkAn3yNwee3nrqDCMXB8MB0SWiUU3GuHnhH7+Qc1IQebJHoFJZR2CPXNOmUzINXbBWKZz+35pQQQXdiKptR3raLSoElfQi18ZC4Pr7xNREGIOM2A=" />
发布主页/关于:
when user visits Home/About, application created " RequestVerificationToken_Lw "cookie with value "pG2/E00Q2DngYxs98f92x9qqrIvrh6zCT/+GGte67NFZLazKFlz++QqMSHpkZ08Qum9vsBCtq7O7MSzCawJkEa2/hdjrWoAcHlDWxxYRWKXm+OxPbqlRs609zam4fK7hReGEX3zf8YR4ltH3oYf4AZgt2mZV31ihRGShiZ7Oy9k="
并遵循表单输入
<input name="__RequestVerificationToken" type="hidden" value="UOCMATdy93A0230aBmRPv5F0xpJlI2urE5sJ4nxsTSWrsi9/xM5qhrxQ4I2vWIjvVrhkW8gSgmGFp7c4XPQUQG5myMGipTAr2/mi5od+Sz6IcfrF2FxwjfWMslt96BcMG6b9BjaGbgnClQOVTkjfHEMIptOYUCTSbVK61dWp5qI=" />
这是我的问题:
非常感谢您的回复!
最佳答案
CSRF 攻击向量的思路是这样的:我在我的网站 https://fake-domain-that-looks-like-a-bank.com 上放了一个恶意表格.我从您的网站上获取了 HTML 和 CSS,所以看起来完全一样。我有一个有效的证书和所有的标志花里胡哨。现在我诱骗用户访问我的网站。
用户看到通常的形式并做一些事情。但是,我替换了一些输入,因此它们无处可去,并且我添加了一些隐藏字段,以便我控制用户(非自愿)做什么,例如替换 'op=modify
与 op=delete
.他的所有行为都由他的(有效的)身份验证 cookie 支持。
现在防伪 token 可以保护用户,因为作为攻击者,我无法将与他的 cookie 匹配的有效隐藏字段添加到我的表单中。如果我能以某种方式读取他的 cookie,我可以简单地窃取身份验证 token ,这会容易得多。
在 MVC 中,防伪 token 与登录用户名绑定(bind)。如果您使用 FormsAuthentication
并且改变用户名的结构,所有已有cookies的用户都会遇到麻烦。附带说明:一个常见问题是维护两个帐户的用户遇到 AntiForgeryTokenExceptions
,如果它是有效的使用场景,您可能需要处理它。
要解决实际问题:
为什么cookie不改变
如果 cookie 值随着每个请求而改变,多标签浏览将是一个问题。
为什么 cookie 和表单值不同
MVC 的 cookie 具有内部结构,因此它们的序列化版本看起来不同。内部的实际安全 token 应该是相同的。序列化程序存储不同的信息,具体取决于存在的信息(用户身份名称等)。还有一个版本字节,指示这是否是 session cookie 等。
坚韧不拔的细节
如果您想了解更多,我建议您通过 http://aspnetwebstack.codeplex.com/ 克隆源代码看看System.Web.WebPages\Helpers\AntiXsrf\TokenValidator.cs
,以及其他文件。无论如何,拥有源代码是非常有帮助的。
关于asp.net-mvc - ASP.NET MVC3 AntiForgeryToken,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14421962/