登录后重新加载 AntiForgeryToken

2023-11-22

在同一页面的另一个视图中成功登录后,我需要在视图中的表单中重新加载 AntiForgeryToken。

我可以通过 jQuery 使用结果登录页面中的新密钥在表单输入 @Html.AntiForgeryToken() 密钥中进行更新吗?

如果是,这是推荐的且安全的吗?

我该怎么做?

EDIT:

在布局中我有不同的部分视图:

部分登录:

<ul class="menudrt" id="headerLogin">
    @{ Html.RenderAction(MVC.Account.LoginHeader()); }
</ul>

在另一个部分中,可以发送评论:

<div class="comentsform">

    <!-- Comments form -->
    @{ Html.RenderAction(MVC.Comment.Create()); }

</div>

要发送评论,用户必须登录,因此登录后,评论表单需要更新 AntiForgeryToken,否则我会收到验证错误,因为现在登录后情况有所不同。

Thanks


出现此问题的原因是 AntiForgery 令牌包含当前经过身份验证的用户的用户名。

所以会发生这样的事情:

  1. 匿名用户导航到您的页面
  2. 为评论表单生成防伪令牌,但该令牌包含空用户名(因为此时用户是匿名的)
  3. 您正在使用 AJAX 调用登录
  4. 用户向服务器提交评论表单,但令牌验证失败,因为初始令牌中包含的空用户名与当前经过身份验证的用户名不同。

因此,您有几个选项可以解决此问题:

  1. 在步骤 3. 中,不要使用 AJAX 调用。使用标准表单提交来登录用户并将其重定向回最初请求的页面。当然,评论表单将被重新加载并为其生成正确的防伪令牌。
  2. 登录后刷新防伪令牌

解决方案 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>
}

好吧,现在当您导航到主页/索引时,将呈现相应的视图,如果您在不先登录的情况下按“评论”按钮,它将起作用。但如果你登录然后评论就会失败。

因此,我们可以添加另一个控制器操作,该操作将通过简单的操作返回部分视图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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

登录后重新加载 AntiForgeryToken 的相关文章

随机推荐