zoukankan      html  css  js  c++  java
  • 15.04.14-登录之后刷新AntiForgeryToken

    用MVC做网站的时候,碰到这样一种情况:

    用户可以匿名访问某页面A,页面可以填写,然后保存数据。访问可以匿名,但是提交的时候会提示登录,然后用户登录之后才能保存。

    这里面的问题

    1. 用户匿名访问页面A

    2. 为提交的表单生成antiforgery token,token中的userName为空

    3. 用ajax登录

    4. 用户提交表单到服务器,但token验证失败。因为当前的token中的userName为空,与已经登录的userName不匹配。

    报错内容:

    提供的防伪标记适用于其他基于声明的用户,而不适用于当前用户

    解决思路:

    1.登录验证成功之后,在后台重新生成有效的token并传递到前台,然后前台更新token。

    Controller:

    //todo:登录验证,成功后执行下面
    string[] roles = new string[] { }; //具体情况设置
    HttpContext.User = new GenericPrincipal(new GenericIdentity(userName), roles);  //用户名具体设置
    
    var ftoken = System.Web.Helpers.AntiForgery.GetHtml().ToString();
    System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"value=""([^""]+)");
    var m = r.Match(ftoken);
    var newToken = m.Groups[1].Value;
    return Json(new { Success = true, Token = newToken }, JsonRequestBehavior.AllowGet);

    View:

    $.post("/Account/FloatLogin", { userID: user, pwd: pwd }, function (res) {
        if (res.Success) {
            closeDialog();
            $("#formID input[name='__RequestVerificationToken']").val(res.Token);
            $("#formID").submit();
        }
        else {
            alert("帐号或密码错误!");
        }
    });

    本来思路应该是没什么问题,但是实际调试时,仍然报错:

    提供的防伪标记适用于用户“admin@example.com”,但当前用户为“”

    这个思路暂时放下。

    2. 登录验证完成之后,单独从服务器获取一次Token。也就是说把登录和更新Token分作两个步骤。

    Controller:

    public int FloatLogin(string userName, string psd)
    {
        var success = true;//伪代码,这里验证身份
        var res = success ? 1 : 0;
    }
    
    public string RefreshToken()
    {
        var ftoken = System.Web.Helpers.AntiForgery.GetHtml().ToString();
        System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex(@"value=""([^""]+)");
        var m = r.Match(ftoken);
        var newToken = m.Groups[1].Value;
        return newToken;
    }

    View:

    $.post("/Account/FloatLogin", { userID: user, pwd: pwd }, function (res) {
        if (res == 1) {
            closeDialog();
            $.get('/Account/RefreshToken', function (newToken) {
                $("#formID input[name='__RequestVerificationToken']").val(newToken);
                $("#formID").submit();
            });
        }
        else {
            alert("帐号或密码错误!");
        }
    });

    这个思路解决了实际的问题。

    参考文档:

    http://stackoverflow.com/questions/16815634/reload-antiforgerytoken-after-a-login

    http://www.cnblogs.com/jiangzhen/p/3870925.html

    http://www.4byte.cn/question/735751/reload-antiforgerytoken-after-a-login.html

    留文备用。第一个思路还有哪部分数据没有写对,留给以后解决吧。

  • 相关阅读:
    [HDOJ4417]Super Mario(归并树)
    [POJ2104] K-th Number(归并树,二分)
    2017北理校赛G题 人民的名义(FFT)
    [CF762C] Two Strings(预处理,二分答案)
    [CF798D] Mike and distribution(贪心,鸽笼原理,随机)
    [CF798C] Mike and gcd problem(规律,gcd)
    2017北理校赛H题 青蛙过河(线段树, dp, 离散化)
    [CF798B] Mike and strings(暴力)
    [CF798A] Mike and palindrome(水题,trick)
    [CCPC2017]湘潭邀请赛
  • 原文地址:https://www.cnblogs.com/icyJ/p/AntiForgeryToken.html
Copyright © 2011-2022 走看看