用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
留文備用。第一個思路還有哪部分數據沒有寫對,留給以后解決吧。