[英]ASP.NET Identity 2 and Anonymous Users
在我們正在開發的電子商務解決方案中,我們使用的是AspNet Identity 2.2.1,要求任何來賓(匿名)用戶必須先完成結帳,而無需事先注冊該網站。 為了滿足此要求,編寫了一個名為UserMigrationAttribute的ActionFilter,該過濾器從cookie中獲取SessionTrackId(字符串GUID)(如果未與請求cookie一起找到SessionTrackId,則從HttpModule為每個請求設置),並在數據庫中創建實際的IdentityUser用戶名,例如SessionTrackId@mydomain.com。
我們已經使用該UserMigration屬性裝飾了BaseController類,以便在整個站點中利用其功能。
到現在為止,所有問題都可以通過一個單獨的問題來解決,即當任何用戶第一次加載頁面時,如果我們嘗試對具有[ValidateAntiForgeryToken]
屬性的方法進行Jquery Ajax調用,則該調用失敗, The provided anti-forgery token was meant for a different claims-based user than the current user.
即使我們在每次ajax調用中都發送__RequestVerificationToken
參數,也會發生錯誤。
但是,如果用戶通過單擊鏈接打開另一個頁面和/或重新加載/刷新當前頁面,則所有后續的ajax調用都將成功完成。
在我們的理解中,UserMigrationAttribute使用OnActionExecuting方法創建用戶,但是在我們在進程@ Html.AntiForgeryToken()中登錄用戶之后,並沒有使用正確的值更新用戶。
您可以在下面找到UserMigrationAttribute代碼;
[AttributeUsage(AttributeTargets.Class)]
public class UserMigrationAttribute : ActionFilterAttribute
{
public ApplicationSignInManager SignInManager(ActionExecutingContext filterContext)
{
return filterContext.HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
public UserManager UserManager(ActionExecutingContext filterContext)
{
return filterContext.HttpContext.GetOwinContext().GetUserManager<UserManager>();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CreateMigrateCurrentUser(filterContext);
base.OnActionExecuting(filterContext);
}
private static readonly object LockThis = new object();
private void CreateMigrateCurrentUser(ActionExecutingContext filterContext)
{
lock (LockThis)
{
var signInManager = SignInManager(filterContext);
var userManager = UserManager(filterContext);
var sessionTrackId = GetSessionTrackId(filterContext);
if (!filterContext.HttpContext.Request.IsAuthenticated)
{
if (!string.IsNullOrEmpty(sessionTrackId))
{
var username = string.Format("{0}@mydomain.com", sessionTrackId);
var user = userManager.FindByName(username);
if (user == null)
{
user = new User() {UserName = username, Email = username};
var result = userManager.Create(user);
userManager.AddToRole(user.Id, StringResources.AnonymousVisitorsGroup);
}
signInManager.SignIn(user, true, true);
}
}
else
{
if (!string.IsNullOrEmpty(sessionTrackId))
{
var username = string.Format("{0}@mydomain.com", sessionTrackId);
var user = userManager.FindByName(username);
if (user != null)
{
if (!HttpContext.Current.User.IsInRole(StringResources.AnonymousVisitorsGroup))
{
var targetUserId = HttpContext.Current.User.Identity.GetUserId<int>();
var service = new Service();
service.Users.MigrateUser(user.Id, targetUserId);
}
}
}
}
}
}
private string GetSessionTrackId(ActionExecutingContext filterContext)
{
var retVal = string.Empty;
if (filterContext.HttpContext.Request.Cookies["stid"] != null)
{
retVal = filterContext.HttpContext.Request.Cookies["stid"].Value;
}
return retVal;
}
}
任何幫助或建議都將受到高度贊賞。
謝謝,
發生這種情況是因為在cookie中設置了防偽令牌,該cookie直到下一個請求才會更新。 如果您是手動登錄用戶,則還應該發出重定向(即使重定向到他們已經前往的頁面),只是為了確保cookie數據正確。 這通常是自然發生的,因為登錄表單將在用戶登錄后重定向到需要授權的URL,從而消除了問題。 由於您當前未重定向,因此數據不同步。
但是,我不得不說,對於這個特定的用例,這似乎是一個非常糟糕的解決方案。 創建某種臨時類型的用戶並登錄該用戶以處理來賓簽出,充其量只會在數據庫中造成不必要的無用數據過剩,最壞的情況下會導致bug和類似的問題。
我還經營一個電子商務網站,我們處理客人結帳的方式非常簡單。 結帳數據僅存儲在會話中(電子郵件,送貨/賬單地址等)。 我們構建了一個視圖模型來處理實際的結帳,提交銷售所需的數據要么來自用戶對象(如果已登錄),要么來自這些會話變量(如果不是)。 如果用戶既未登錄,也未設置必需的會話變量,則它們將被重定向到收集帳單/運費等的入職表格。
對於其他方面,例如維護匿名購物車,我們使用帶有購物車標識符的永久cookie。 如果該用戶最終創建了一個帳戶,我們將匿名購物車與其用戶相關聯,然后刪除該cookie。 這樣可以確保他們的購物車在會話超時和關閉瀏覽器之類的情況下都可以生存,即使他們是匿名的也是如此。
換句話說,在所有這些情況下,實際上不需要用戶對象。 如果它在那里(用戶已登錄),很好,我們將使用它。 否則,我們將收集並保留通過其他方式結帳的必要信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.