2017-08-03 4 views
1

In unserer sich entwickelnden E-Commerce-Lösung verwenden wir AspNet Identity 2.2.1 und es ist erforderlich, dass alle (anonymen) Gäste das Auschecken ohne vorherige Registrierung auf der Website durchführen. Um diese Anforderung zu erfüllen, haben wir einen ActionFilter mit dem Namen UserMigrationAttribute geschrieben, der SessionTrackId (string GUID) von cookie - was wir für jede Anfrage aus einem HttpModule setzen, wenn SessionTrackId nicht zusammen mit Anfragecookies gefunden wird - erzeugt und IdentityUser in der Datenbank erstellt benutze etwas wie [email protected]ASP.NET Identity 2 und anonyme Benutzer

Wir haben unsere BaseController-Klasse mit diesem UserMigration-Attribut versehen, um dessen Funktionen auf der gesamten Site nutzen zu können.

Alles funktioniert bis zu diesem Punkt wie erwartet mit Single Downside Problem, das ist, wenn die Seite zum ersten Mal für einen Benutzer geladen wird, wenn wir versuchen, einen Jquery Ajax Call zu einer Methode zu machen, die [ValidateAntiForgeryToken] Attribut haben, Der Aufruf schlägt mit dem Fehler 'The provided anti-forgery token was meant for a different claims-based user than the current user.' fehl, obwohl wir bei jedem Ajax-Aufruf den Parameter __RequestVerificationToken senden.

Wenn der Benutzer jedoch eine andere Seite öffnet, indem er auf den Link klickt und/oder die aktuelle Seite neu lädt, werden alle nachfolgenden Ajax-Aufrufe erfolgreich abgeschlossen.

In unserem Verständnis erstellt UserMigrationAttribute Benutzer auf OnActionExecuting-Methode, aber nachdem wir Benutzer im Prozess anmelden @ Html.AntiForgeryToken() wird nicht mit den richtigen Werten aktualisiert.

Sie können den UserMigrationAttribute-Code unten finden;

[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; 

     } 

    } 

Jede Hilfe oder Vorschläge werden sehr geschätzt.

Danke,

Antwort

1

Dies geschieht, weil die Fälschungstoken in einem Cookie gesetzt werden, die nicht bis zur nächsten Anforderung aktualisiert wird. Wenn Sie einen Benutzer manuell signieren, sollten Sie auch eine Weiterleitung (auch auf derselben Seite, zu der sie bereits weitergeleitet wurden) erstellen, um sicherzustellen, dass die Cookie-Daten korrekt sind. Dies geschieht normalerweise auf natürliche Weise, da das Anmeldeformular auf die URL umleitet, die nach der Anmeldung des Benutzers autorisiert werden muss, wodurch das Problem behoben wird. Da Sie derzeit nicht umleiten, sind die Daten nicht synchronisiert.

Allerdings muss ich sagen, dass dies scheint eine sehr schlechte Lösung für diesen speziellen Anwendungsfall. Wenn Sie eine Art temporären Benutzer erstellen und diesen Benutzer für die Abwicklung des Gäste-Checkouts anmelden, entsteht im besten Fall unnötige Flut nutzloser Daten in Ihrer Datenbank und führt im schlimmsten Fall zu Fehlern und anderen Problemen wie dieser.

Ich betreibe auch eine E-Commerce-Website, und die Art und Weise, wie wir Gäste Kasse behandelt ist unglaublich einfach. Die Checkout-Daten werden nur in der Sitzung gespeichert (E-Mail, Versand-/Rechnungsadresse usw.). Wir erstellen ein View-Modell, um die eigentliche Prüfung abzuwickeln, bei der die Daten, die für die Einreichung des Verkaufs benötigt werden, entweder vom Benutzerobjekt stammen, wenn sie angemeldet sind, oder von diesen Sitzungsvariablen, falls dies nicht der Fall ist. Wenn der Benutzer weder angemeldet ist noch die erforderlichen Sitzungsvariablen festgelegt hat, werden sie zum Onboarding-Formular weitergeleitet, wo Abrechnung/Versand usw. gesammelt wird.

Für andere Aspekte wie die Pflege eines anonymen Einkaufswagens verwenden wir einen permanenten Cookie mit der Wagenkennung. Wenn der Benutzer ein Konto erstellt, verknüpfen wir den anonymen Einkaufswagen mit seinem Benutzer und entfernen dann das Cookie. Dadurch wird sichergestellt, dass der Einkaufswagen nach dem Sitzungszeitlimit und dem Schließen des Browsers, auch wenn sie anonym sind, überlebt.

Mit anderen Worten, in all diesen Dingen wird eigentlich kein Benutzerobjekt benötigt. Wenn es da ist (Benutzer ist eingeloggt), großartig, wir werden es benutzen. Andernfalls sammeln und speichern wir die erforderlichen Informationen für den Kauf auf andere Weise.

+0

Vielen Dank für Ihre Antwort und Anleitung, das ist die akzeptierte Antwort, da es (selbst) Redirect auf FilterContext schlägt somit unser Problem zu lösen. –

Verwandte Themen