简体   繁体   English

ASP.NET Identity 2和匿名用户

[英]ASP.NET Identity 2 and Anonymous Users

In our developing e-commerce solution we are using AspNet Identity 2.2.1 and it is required that any guest (anonymous) users should complete checkout without prior registration to the website. 在我们正在开发的电子商务解决方案中,我们使用的是AspNet Identity 2.2.1,要求任何来宾(匿名)用户必须先完成结帐,而无需事先注册该网站。 In order to fullfill this requirement have written an ActionFilter named UserMigrationAttribute which obtains SessionTrackId (string GUID) from cookie -which we set from a HttpModule for every request if SessionTrackId is not found along with request cookies- and creates and actual IdentityUser in database with the username something like SessionTrackId@mydomain.com. 为了满足此要求,编写了一个名为UserMigrationAttribute的ActionFilter,该过滤器从cookie中获取SessionTrackId(字符串GUID)(如果未与请求cookie一起找到SessionTrackId,则从HttpModule为每个请求设置),并在数据库中创建实际的IdentityUser用户名,例如SessionTrackId@mydomain.com。

We have decorated our BaseController class with this UserMigration attribute in order to utilize its functions throughout the site. 我们已经使用该UserMigration属性装饰了BaseController类,以便在整个站点中利用其功能。

Everything up to this point works as expected with single downside issue, which is when the page is being loaded for the first time for any user, if we try to make an Jquery Ajax Call to a Method which have [ValidateAntiForgeryToken] attribute, the call fails with the ' The provided anti-forgery token was meant for a different claims-based user than the current user. 到现在为止,所有问题都可以通过一个单独的问题来解决,即当任何用户第一次加载页面时,如果我们尝试对具有[ValidateAntiForgeryToken]属性的方法进行Jquery Ajax调用,则该调用失败, The provided anti-forgery token was meant for a different claims-based user than the current user. ' error, even though we are sending __RequestVerificationToken parameter with every ajax call. 即使我们在每次ajax调用中都发送__RequestVerificationToken参数,也会发生错误。

But if user opens another page by clicking link and/or reloads/refreshes current page, all the subsequent ajax calls complete successfully. 但是,如果用户通过单击链接打开另一个页面和/或重新加载/刷新当前页面,则所有后续的ajax调用都将成功完成。

In our understanding UserMigrationAttribute creates user on OnActionExecuting method, but after we signIn user in the process @Html.AntiForgeryToken() is not being updated with the right values. 在我们的理解中,UserMigrationAttribute使用OnActionExecuting方法创建用户,但是在我们在进程@ Html.AntiForgeryToken()中登录用户之后,并没有使用正确的值更新用户。

You may find the UserMigrationAttribute code below; 您可以在下面找到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;

        }

    }

Any help or suggestions are highly appreciated. 任何帮助或建议都将受到高度赞赏。

Thank you, 谢谢,

This is happening because the anti-forgery token is set in a cookie, which will not be updated until the next request. 发生这种情况是因为在cookie中设置了防伪令牌,该cookie直到下一个请求才会更新。 If you're manually signing a user in, you should also issue a redirect (even if to the same page they were already headed to), simply to ensure that the cookie data is correct. 如果您是手动登录用户,则还应该发出重定向(即使重定向到他们已经前往的页面),只是为了确保cookie数据正确。 This normally happens naturally, as the sign in form will redirect to the URL that needed authorization after the user is signed in, thus negating the problem. 这通常是自然发生的,因为登录表单将在用户登录后重定向到需要授权的URL,从而消除了问题。 Since you're not redirecting currently, the data is out of sync. 由于您当前未重定向,因此数据不同步。

However, I have to say that this seems like a very poor solution to this particular use case. 但是,我不得不说,对于这个特定的用例,这似乎是一个非常糟糕的解决方案。 Creating some sort of temporary-type user and signing that user in to handle guest checkout creates an unnecessary glut of useless data in your database, at best, and leads to bugs and other issues like this one you're experiencing, at worst. 创建某种临时类型的用户并登录该用户以处理来宾签出,充其量只会在数据库中造成不必要的无用数据过剩,最坏的情况下会导致bug和类似的问题。

I also run an ecommerce site, and the way we handled guest checkout is incredibly simplistic. 我还经营一个电子商务网站,我们处理客人结帐的方式非常简单。 The checkout data is just stored in the session (email, shipping/billing address, etc.). 结帐数据仅存储在会话中(电子邮件,送货/账单地址等)。 We build a view model to handle the actual checkout where the data necessary for submitting the sale comes either from the user object, if they're logged in, or these session variables, if they aren't. 我们构建了一个视图模型来处理实际的结帐,提交销售所需的数据要么来自用户对象(如果已登录),要么来自这些会话变量(如果不是)。 If the user is neither logged in, nor has the requisite session variables set, then they are redirected to the onboarding form where billing/shipping, etc. is collected. 如果用户既未登录,也未设置必需的会话变量,则它们将被重定向到收集帐单/运费等的入职表格。

For other aspects like maintaining an anonymous cart, we use a permanent cookie with the cart identifier. 对于其他方面,例如维护匿名购物车,我们使用带有购物车标识符的永久cookie。 If the user ends up creating an account, we associate the anonymous cart with their user, and then remove the cookie. 如果该用户最终创建了一个帐户,我们将匿名购物车与其用户相关联,然后删除该cookie。 This ensures that their cart survives past the session timeout and things like closing the browser, even if they're anonymous. 这样可以确保他们的购物车在会话超时和关闭浏览器之类的情况下都可以生存,即使他们是匿名的也是如此。

In other words, in all these things, no user object is actually needed. 换句话说,在所有这些情况下,实际上不需要用户对象。 If it's there (user is logged in), great, we'll use it. 如果它在那里(用户已登录),很好,我们将使用它。 Otherwise, we collect and persist the requisite information for checkout via other means. 否则,我们将收集并保留通过其他方式结帐的必要信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM