更新时间:2023-12-03 15:52:10
该问题发生,因为防伪标记包含当前已验证用户的用户名。
The issue is occurring because the AntiForgery token contains the username of the currently authenticated user.
因此,这里发生了什么:
So here's what happens:
所以,你有几个选项来解决这个问题:
So you have a couple of options to fix this issue:
解决方案1.显而易见并没有使它成为一个很好的候选用于覆盖在我的答案。让我们来看看第二个解决方案如何实施。
The obviousness of solution 1. doesn't make it a good candidate for covering it in my answer. Let's see how the second solution could be implemented.
但是,首先让我们来重现问题用一个例子:
But first let's reproduce the problem with an example:
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login()
{
FormsAuthentication.SetAuthCookie("john", false);
return Json(new { success = true });
}
[HttpPost]
[ValidateAntiForgeryToken()]
public ActionResult Comment()
{
return Content("Thanks for commenting");
}
}
〜/查看/主页/ Index.cshtml
:
<div>
@{ Html.RenderPartial("_Login"); }
</div>
<div id="comment">
@{ Html.RenderPartial("_Comment"); }
</div>
<script type="text/javascript">
$('#loginForm').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
alert('You are now successfully logged in');
}
});
return false;
});
</script>
〜/查看/主页/ _Login.cshtml
:
@using (Html.BeginForm("Login", null, FormMethod.Post, new { id = "loginForm" }))
{
@Html.AntiForgeryToken()
<button type="submit">Login</button>
}
〜/查看/主页/ _Comment.cshtml
:
@using (Html.BeginForm("Comment", null, FormMethod.Post))
{
@Html.AntiForgeryToken()
<button type="submit">Comment</button>
}
好吧,现在当您导航到主/指数对应的视图将呈现,如果你的评论按钮preSS没有记录,在首先它会工作。但是,如果您登录,然后评论将失败。
Alright now when you navigate to the Home/Index the corresponding view will be rendered and if you press on the Comment button without logging-in first it will work. But if you login and then Comment it will fail.
因此,我们可以添加另一个控制器动作,将在以产生新的令牌返回一个简单的 Html.AntiForgeryToken
调用局部视图:
So we could add another controller action that will return a partial view with a simple Html.AntiForgeryToken
call in order to generate a fresh token:
public ActionResult RefreshToken()
{
return PartialView("_AntiForgeryToken");
}
和相应的部分(〜/查看/主页/ _AntiForgeryToken.cshtml
)
@Html.AntiForgeryToken()
和最后一步是通过更新我们的AJAX调用刷新令牌:
And the final step is to refresh the token by updating our AJAX call:
<script type="text/javascript">
$('#loginForm').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
$.get('@Url.Action("RefreshToken")', function (html) {
var tokenValue = $('<div />').html(html).find('input[type="hidden"]').val();
$('#comment input[type="hidden"]').val(tokenValue);
alert('You are now successfully logged in and can comment');
});
}
});
return false;
});
</script>