在同一页中的另一个视图中成功登录后,我需要重新加载位于视图中的表单中的AntiForgeryToken。
我可以通过jQuery从结果登录页面使用新的表单输入@Html.AntiForgeryToken()键进行更新吗?
如果是,这是推荐的和安全的吗?
我该怎么做呢?
编辑:
在布局中,我有不同的PartialViews:
登录的部分:
<ul class="menudrt" id="headerLogin">
    @{ Html.RenderAction(MVC.Account.LoginHeader()); }
</ul>在另一个部分中,可以发送评论:
<div class="comentsform">
    <!-- Comments form -->
    @{ Html.RenderAction(MVC.Comment.Create()); }
</div>要发送评论,用户必须登录,所以在登录之后,评论表单需要更新AntiForgeryToken,否则我会得到验证错误,因为现在登录已经不同了。
谢谢
发布于 2013-06-07 14:26:35
发生此问题的原因是AntiForgery令牌包含当前已通过身份验证的用户的用户名。
因此,下面是发生的事情:
<代码>G29
因此,您有几个选项来解决此问题:
步骤3中的
后刷新防伪令牌
解决方案1的显而易见并不能使它成为我的答案中涵盖它的一个很好的候选者。让我们看看第二个解决方案是如何实现的。
但首先让我们用一个例子来重现这个问题:
控制器:
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");
    }
}~/Views/Home/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>~/Views/Home/_Login.cshtml
@using (Html.BeginForm("Login", null, FormMethod.Post, new { id = "loginForm" }))
{
    @Html.AntiForgeryToken()
    <button type="submit">Login</button>
}~/Views/Home/_Comment.cshtml
@using (Html.BeginForm("Comment", null, FormMethod.Post))
{ 
    @Html.AntiForgeryToken()
    <button type="submit">Comment</button>
}好的,现在当你导航到Home/Index时,相应的视图将被渲染,如果你在没有登录的情况下按下Comment按钮,它将会工作。但是如果你登录然后评论,它将会失败。
因此,我们可以添加另一个控制器操作,该操作将通过一个简单的Html.AntiForgeryToken调用返回部分视图,以生成一个新的令牌:
public ActionResult RefreshToken()
{
    return PartialView("_AntiForgeryToken");
}和相应的部分(~/Views/Home/_AntiForgeryToken.cshtml):
@Html.AntiForgeryToken()最后一步是通过更新AJAX调用来刷新令牌:
<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>发布于 2013-06-07 03:14:03
您只需在用户登录后返回AntiForgeryToken即可实现此目的。
不需要重复使用相同的令牌2次。
控制器:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
  // do something with login
  // return new token as a partial to parse and get value
  return this.PartialView("_AntiForgeryPartial");
}_AntiForgeryPartial:
@Html.AntiForgeryToken()您可以使用与此类似的JS将新的AntiForgeryToken值加载到注释表单中。
视图:
$("#LoginForm").submit(function (e) {
    e.preventDefault();
    var $this = $(this);
    $.ajax({
        type: $this.attr("method"),
        url: $this.attr("action"),
        data: $this.serialize(),
        success: function (response) {
            // get the new token from the response html
            var val = $(response).find('input[type="hidden"]').val();
            // set the new token value
            $('.commentsform input[type="hidden"]').val(val);
        }
    });
});当评论表单完成POST时,您应该能够针对新的唯一AntiForgeryToken进行验证。
AntiForgeryToken()上的Steven Sanderson has a great post,如果您想了解更多关于如何使用它以及它的用途的话。
https://stackoverflow.com/questions/16815634
复制相似问题