【发布时间】:2018-01-11 06:29:58
【问题描述】:
在我们开发的电子商务解决方案中,我们使用的是 AspNet Identity 2.2.1,并且要求任何来宾(匿名)用户都必须在未事先注册网站的情况下完成结帐。为了满足这个要求,我们编写了一个名为 UserMigrationAttribute 的 ActionFilter,它从 cookie 中获取 SessionTrackId(字符串 GUID)——如果没有找到 SessionTrackId 和请求 cookie,我们从 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;
}
}
非常感谢任何帮助或建议。
谢谢,
【问题讨论】:
标签: c# asp.net-mvc asp.net-identity anonymous-users