MVC3 AntiForgeryToken在Ajax登录时出现问题。

13 浏览
0 Comments

MVC3 AntiForgeryToken在Ajax登录时出现问题。

ASP.NET MVC的AntiForgeryToken机制基于当前的HttpContext.User。当调用Html.AntiForgeryToken()时,它使用该值来构建令牌。基本上它是可以的(在此处的最后一段有解释),但是当通过Ajax调用登录时就会出现问题。\n在我的代码中,当用户登录时,凭据以Json对象的形式通过Ajax发送(AntiForgeryToken隐藏字段值也在Json中发送),服务器对用户进行身份验证,应用FormsAuthentication.SetAuthCookie(),并返回一个包含一些特定用户数据的Json结果。通过这种方式,我可以避免在登录时进行完整页面刷新。\n问题是,每个随后的Ajax请求到服务器现在都会在ValidateAntiForgeryTokenAttribute上失败,因为它现在期望一个与防伪cookie不兼容的防伪令牌。\n我试图手动获取一个新的隐藏字段令牌(在操作上使用AntiForgery.GetHtml(),提取令牌字符串本身,将其以Json形式返回给客户端,并在JavaScript中手动放置在防伪隐藏字段中),但它不起作用 - 随后的Ajax调用在服务器上的ValidateAntiForgeryTokenAttribute失败。\n实际上,每次调用AntiForgery.GetHtml()(本质上是Html.AntiForgeryToken()助手所做的)都会产生一个不同的令牌,这会使先前的令牌无效。\n我还尝试设置HttpContext.User = new GenericPrincipal(new GenericIdentity(email), null);,如此处详细说明,但它不起作用。\n注意:此解决方案对我不起作用,因为我的特定情况:一个更改服务器上用户身份的Ajax登录,因此在登录之前生成的每个令牌都无效。另外,此解决方案也不适用,因为它解决的是不同的问题。

0
0 Comments

MVC3 AntiForgeryToken breaks on Ajax login

问题出现的原因:

该问题是由于在使用Ajax登录时,MVC3的AntiForgeryToken出现了问题。具体来说,问题出现在将stackoverflow中的一个答案与一个部分组合使用时。在代码中引入了一个名为AntiForgeryToken的部分,该部分包含了AntiForgeryToken()方法。

解决方法:

为了解决这个问题,首先需要在登录/注销时更新令牌。在JavaScript和jQuery代码中,需要在发送登录/注销的Ajax请求之后进行令牌的更新。具体代码如下:

$(document).ready(function () {
    AddAntiForgeryToken = function (data) {
        data.__RequestVerificationToken = $('#__AjaxAntiForgeryForm input[name=__RequestVerificationToken]').val();
        return data;
    };
    var viewmodel = function () {
        var vm = this;
        vm.signedIn = ko.observable(false);
        vm.signIn = function () {
            $.post('Home/SignIn', function () {
                vm.signedIn(true);
                $.get('Home/GetAuthToken', function (newToken) {
                    $('#__AjaxAntiForgeryForm').html(newToken);
                });
            });
        };
        vm.signOut = function () {
            $.post('Home/SignOut', function () {
                vm.signedIn(false);
                $.get('Home/GetAuthToken', function (newToken) {
                    $('#__AjaxAntiForgeryForm').html(newToken);
                });
            });
        };
        vm.testToken = function () {
            $.post('Home/TestToken', AddAntiForgeryToken({ stuff: 'stuff' }));
        };
    };
    ko.applyBindings(new viewmodel(), $('#loginTestView')[0]);
});

这段代码中,需要注意的是$.get请求需要在$.post请求之后发生,以确保在实际登录之前令牌已更新。需要注意的是,这段代码可以进行进一步的优化,但是上述是主要的解决方法。如果在其他情况下令牌需要更新,只需要再次调用更新部分的方法。

以上就是解决MVC3 AntiForgeryToken在Ajax登录中出现问题的原因以及解决方法。

0
0 Comments

问题原因:登录时,需要清除并重新生成现有的表单令牌。这意味着登录代码必须刷新当前页面(这样会破坏Ajax部分),重新实现令牌,或者刷新令牌。可以请求部分视图,提取令牌并更新表单。可以创建一个RESTful URL,只向经过身份验证的用户返回令牌。有人可能会认为这是一个安全问题,但我不这么认为,因为这只是一个更容易获取令牌的方法,而不是请求任何视图-部分视图或其他视图。

解决方法:可以通过以下方式轻松获取要替换的令牌实例:

var token = $('input[name=""__RequestVerificationToken""]');

编辑后的问题:如果用户未登录,为什么在表单上要有一个令牌。您允许相同的表单在未登录和登录的情况下进行“操作”吗?大多数网站即使在这种情况下也会重定向到登录页面。我是否正确理解了这一点?如果是这样的话,您可能要考虑在这里跳过令牌,或者为未经身份验证的用户使用第二种类型的令牌。我相信您的意思是未经身份验证的用户可以在应用程序中提交某些东西-如果我正确理解了这一点的话。

至于您最后的问题,为什么未经身份验证的用户需要一个令牌,请参阅我对Ben评论的回答。我将尝试创建一个具有令牌的部分视图,并向您更新结果。听起来像个好主意!

还没有做到这一点,但我会接受您的答案,因为它听起来很有希望 🙂

0