C# ASP.NET Identity 2和匿名用户
在我们开发的电子商务解决方案中,我们使用的是AspNet Identity 2.2.1,要求任何来宾(匿名)用户在未事先注册网站的情况下完成结账。为了满足这个要求,我们编写了一个名为UserMigrationAttribute的ActionFilter,它获取SessionTrackId(字符串GUID)从cookie(如果在请求cookie中找不到SessionTrackId,则我们从HttpModule为每个请求设置该cookie),并在数据库中创建和实际标识用户,用户名如下SessionTrackId@mydomain.com. 我们用这个UserMigration属性修饰了BaseController类,以便在整个站点中使用它的功能 到目前为止的一切都与预期的一样,只有一个缺点,即当任何用户第一次加载页面时,如果我们尝试对具有C# ASP.NET Identity 2和匿名用户,c#,asp.net-mvc,asp.net-identity,anonymous-users,C#,Asp.net Mvc,Asp.net Identity,Anonymous Users,在我们开发的电子商务解决方案中,我们使用的是AspNet Identity 2.2.1,要求任何来宾(匿名)用户在未事先注册网站的情况下完成结账。为了满足这个要求,我们编写了一个名为UserMigrationAttribute的ActionFilter,它获取SessionTrackId(字符串GUID)从cookie(如果在请求cookie中找不到SessionTrackId,则我们从HttpModule为每个请求设置该cookie),并在数据库中创建和实际标识用户,用户名如下SessionT
[ValidateAntiForgeryToken]
属性的方法进行Jquery Ajax调用,调用失败,原因是“提供的防伪令牌针对的是与当前用户不同的基于声明的用户。
”错误,即使我们在每个ajax调用中都发送\uu 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;
}
}
[AttributeUsage(AttributeTargets.Class)]
公共类UserMigrationAttribute:ActionFilterAttribute
{
公共应用程序SignInManager SignInManager(ActionExecutingContext筛选器上下文)
{
返回filterContext.HttpContext.GetOwinContext().Get();
}
公共用户管理器用户管理器(ActionExecutingContext筛选器上下文)
{
返回filterContext.HttpContext.GetOwinContext().GetUserManager();
}
公共覆盖无效OnActionExecuting(ActionExecutingContext filterContext)
{
CreateMigrateCurrentUser(filterContext);
base.OnActionExecuting(filterContext);
}
私有静态只读对象LockThis=新对象();
私有void CreateMigrateCurrentUser(ActionExecutingContext筛选器上下文)
{
锁定(锁定此)
{
var signInManager=signInManager(filterContext);
var userManager=userManager(filterContext);
var sessionTrackId=GetSessionTrackId(filterContext);
如果(!filterContext.HttpContext.Request.IsAuthenticated)
{
如果(!string.IsNullOrEmpty(sessionTrackId))
{
var username=string.Format(“{0}@mydomain.com”,sessionTrackId);
var user=userManager.FindByName(用户名);
if(user==null)
{
user=newuser(){UserName=UserName,Email=UserName};
var result=userManager.Create(用户);
userManager.AddToRole(user.Id,StringResources.AnonymousVisitorsGroup);
}
signInManager.SignIn(用户,true,true);
}
}
其他的
{
如果(!string.IsNullOrEmpty(sessionTrackId))
{
var username=string.Format(“{0}@mydomain.com”,sessionTrackId);
var user=userManager.FindByName(用户名);
如果(用户!=null)
{
if(!HttpContext.Current.User.IsInRole(StringResources.AnonymousVisitorsGroup))
{
var targetUserId=HttpContext.Current.User.Identity.GetUserId();
var服务=新服务();
service.Users.MigrateUser(user.Id,targetUserId);
}
}
}
}
}
}
私有字符串GetSessionTrackId(ActionExecutingContext筛选器上下文)
{
var retVal=string.Empty;
if(filterContext.HttpContext.Request.Cookies[“stid”]!=null)
{
retVal=filterContext.HttpContext.Request.Cookies[“stid”].Value;
}
返回返回;
}
}
非常感谢您的帮助或建议
谢谢,发生这种情况是因为防伪令牌设置在cookie中,在下一个请求之前不会更新。如果您手动登录用户,您还应该发出重定向(即使重定向到他们已经指向的同一页面),以确保cookie数据正确。这通常是自然发生的,因为登录表单将在用户登录后重定向到需要授权的URL,从而消除问题。由于当前未重定向,因此数据不同步 然而,我不得不说,对于这个特定的用例来说,这似乎是一个非常糟糕的解决方案。创建某种临时类型的用户并将该用户登录以处理来宾签出最多会在数据库中创建不必要的无用数据,最坏的情况是会导致错误和其他问题,比如您正在经历的问题 我还经营一个电子商务网站,我们处理客人结账的方式非常简单。签出数据只存储在会话中(电子邮件、发货/账单地址等)。我们构建了一个视图模型来处理提交销售所需数据的实际结帐