it-swarm.com.de

Das Anti-Fälschungs-Token ist für den Benutzer "" gedacht, der aktuelle Benutzer ist jedoch "Benutzername".

Ich baue eine Einzelseitenanwendung und habe ein Problem mit Anti-Fälschungs-Token.

Ich weiß, warum das Problem passiert. Ich weiß einfach nicht, wie ich es beheben kann.

Ich erhalte die Fehlermeldung, wenn Folgendes passiert:

  1. Nicht angemeldeter Benutzer lädt ein Dialogfeld (mit einem generierten Fälschungs-Token).
  2. Benutzer schließt den Dialog
  3. Benutzer meldet sich an
  4. Benutzer öffnet den gleichen Dialog 
  5. Benutzer sendet das Formular im Dialog

Das Anti-Fälschungs-Token ist für den Benutzer "" gedacht, der aktuelle Benutzer ist jedoch "Nutzername"

Der Grund dafür ist, dass meine Anwendung zu 100% aus einer Einzelseite besteht. Wenn sich ein Benutzer erfolgreich über einen Ajax-Post-Code bei /Account/JsonLogin anmeldet, wechsle ich die aktuellen Ansichten einfach mit den "authentifizierten Ansichten", die vom Server zurückgegeben werden, aber do Laden Sie die Seite nicht neu.

Ich weiß, das ist der Grund, denn wenn ich die Seite zwischen Schritt 3 und 4 einfach neu lade, liegt kein Fehler vor.

Es scheint also, dass @Html.AntiForgeryToken() im geladenen Formular immer noch ein Token für den alten Benutzer zurückgibt, bis die Seite neu geladen wird.

Wie kann ich @Html.AntiForgeryToken() so ändern, dass ein Token für den neuen authentifizierten Benutzer zurückgegeben wird?

Ich füge eine neue GenericalPrincipal mit einer benutzerdefinierten IIdentity in jeden Application_AuthenticateRequest ein. Wenn also @Html.AntiForgeryToken() aufgerufen wird, heißt HttpContext.Current.User.Identity in der Tat. Meine benutzerdefinierte Identität mit IsAuthenticated -Eigenschaft ist auf true gesetzt, und @Html.AntiForgeryToken scheint immer noch ein Token für den alten Benutzer darzustellen, es sei denn, ich mache ein Seite neu laden.

114
parliament

Dies geschieht, weil das fälschungssichere Token den Benutzernamen des Benutzers als Teil des verschlüsselten Token zur besseren Überprüfung einbettet. Wenn Sie zum ersten Mal @Html.AntiForgeryToken() aufrufen, ist der Benutzer nicht angemeldet, so dass das Token nach der Anmeldung des Benutzers eine leere Zeichenfolge für den Benutzernamen enthält. Wenn Sie das Anti-Fälschungs-Token nicht ersetzen, wird die Überprüfung nicht bestanden, da das ursprüngliche Token bereits vorhanden war für anonyme Benutzer und jetzt haben wir einen authentifizierten Benutzer mit einem bekannten Benutzernamen.

Sie haben einige Möglichkeiten, um dieses Problem zu lösen:

  1. Lassen Sie Ihr SPA diesmal einen vollständigen POST durchführen, und wenn die Seite neu geladen wird, wird ein Anti-Fälschungs-Token mit dem aktualisierten Benutzernamen angezeigt.

  2. Sie haben eine Teilansicht mit nur @Html.AntiForgeryToken() und führen direkt nach der Anmeldung eine weitere AJAX - Anforderung aus, und ersetzen Sie Ihren vorhandenen fälschungssicheren Token durch die Antwort der Anforderung.

  3. Deaktivieren Sie einfach die Identitätsprüfung, die von der fälschungssicheren Validierung durchgeführt wird. Fügen Sie der Application_Start -Methode Folgendes hinzu:AntiForgeryConfig.SuppressIdentityHeuristicChecks = true.

163
epignosisx

Um den Fehler zu beheben, müssen Sie die OutputCache Data Annotation auf der Seite Get ActionResult of Login abrufen als:

[OutputCache(NoStore=true, Duration = 0, VaryByParam= "None")] 
public ActionResult Login(string returnUrl)
20
user3401354

Es passiert oft mit meiner Bewerbung, also entschied ich mich dafür zu googeln!

Ich habe eine einfache Erklärung zu diesem Fehler gefunden. Die Benutzer doppelklicken auf die Schaltfläche zum Anmelden! Auf dem folgenden Link können Sie einen anderen Benutzer darüber sprechen sehen:

MVC 4: Das fälschungssichere Token war für Benutzer "" gedacht, der aktuelle Benutzer ist jedoch "Benutzer" .

Ich hoffe, es hilft! =)

8
Ricardo França

Ich hatte das gleiche Problem, und dieser dreckige Hack hat ihn behoben, zumindest bis ich ihn sauberer reparieren kann.

    public ActionResult Login(string returnUrl)
    {
        if (AuthenticationManager.User.Identity.IsAuthenticated)
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Login");
        }

...

4
Saúl Jacinto

Ich hatte ein ziemlich spezifisches, aber ähnliches Problem im Registrierungsprozess. Sobald der Benutzer auf den an ihn gesendeten E-Mail-Link geklickt hat, wird er angemeldet und direkt an den Bildschirm mit den Kontodetails gesendet, um weitere Informationen einzugeben. Mein Code war:

    Dim result = Await UserManager.ConfirmEmailAsync(userId, code)
    If result.Succeeded Then
        Dim appUser = Await UserManager.FindByIdAsync(userId)
        If appUser IsNot Nothing Then
            Dim signInStatus = Await SignInManager.PasswordSignInAsync(appUser.Email, password, True, shouldLockout:=False)
            If signInStatus = SignInStatus.Success Then
                Dim identity = Await UserManager.CreateIdentityAsync(appUser, DefaultAuthenticationTypes.ApplicationCookie)
                AuthenticationManager.SignIn(New AuthenticationProperties With {.IsPersistent = True}, identity)
                Return View("AccountDetails")
            End If
        End If
    End If

Ich fand, dass die Rückgabeansicht ("AccountDetails") mir die Tokenausnahme gab. Ich vermute, da die ConfirmEmail-Funktion mit AllowAnonymous dekoriert war, die AccountDetails-Funktion jedoch ValidateAntiForgeryToken hatte.

Das Ändern des Return to Return RedirectToAction ("AccountDetails") löste das Problem für mich.

1
Liam
[OutputCache(NoStore=true, Duration=0, VaryByParam="None")]

public ActionResult Login(string returnUrl)

Sie können dies testen, indem Sie in der ersten Zeile Ihrer Login (Get) -Aktion einen Haltepunkt setzen. Vor dem Hinzufügen der OutputCache-Direktive wird der Haltepunkt beim ersten Laden getroffen, aber nach dem Klicken auf die Zurück-Schaltfläche des Browsers wird er nicht angezeigt. Nach dem Hinzufügen der Direktive sollten Sie am Ende jedes Mal den Haltepunkt treffen, sodass das AntiForgeryToken das richtige und nicht das leere ist.

1
Marian Dalalau

Ich habe dieselbe Ausnahme, die meistens auf dem Produktionsserver auftritt.

Warum passiert das?

Dies geschieht, wenn sich der Benutzer mit gültigen Anmeldeinformationen anmeldet und einmal angemeldet ist und zu einer anderen Seite weitergeleitet wird. Nachdem er auf die Zurück-Schaltfläche geklickt hat, wird die Anmeldeseite angezeigt, und er hat erneut gültige Anmeldeinformationen eingegeben, als diese Ausnahme auftritt.

Wie löst man?

Fügen Sie einfach diese Zeile hinzu und arbeiten Sie perfekt, ohne einen Fehler zu erhalten.

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
1
Brijesh Mavani

Die Nachricht wird angezeigt, wenn Sie sich anmelden, wenn Sie bereits authentifiziert sind.

Dieser Helper macht genau das gleiche wie das [ValidateAntiForgeryToken]-Attribut.

System.Web.Helpers.AntiForgery.Validate()

Entfernen Sie das [ValidateAntiForgeryToken]-Attribut vom Controller und setzen Sie diesen Helfer in Aktion.

Wenn der Benutzer bereits authentifiziert ist, leiten Sie ihn zur Startseite weiter, oder führen Sie nach dieser Überprüfung die Überprüfung des gültigen Fälschungsschutztokens fort.

if (User.Identity.IsAuthenticated)
{
    return RedirectToAction("Index", "Home");
}

System.Web.Helpers.AntiForgery.Validate();

Um zu versuchen, den Fehler zu reproduzieren, gehen Sie wie folgt vor: Wenn Sie sich auf Ihrer Anmeldeseite befinden und nicht authentifiziert sind. Wenn Sie die Registerkarte duplizieren und sich mit der zweiten Registerkarte anmelden, ___. Wenn Sie zur ersten Registerkarte der Anmeldeseite zurückkehren und versuchen, sich anzumelden, ohne die Seite erneut zu laden, haben Sie diesen Fehler.

0
A. Morel

Ich hatte das gleiche Problem mit einer ASP.NET MVC Core-Anwendung mit einer Seite. Ich habe das Problem gelöst, indem Sie in allen Controller-Aktionen HttpContext.User gesetzt haben, die die aktuellen Identitätsansprüche ändern (da MVC dies nur für nachfolgende Anforderungen ausführt, wie hier hier ). Ich habe einen Ergebnisfilter anstelle von Middleware verwendet, um die Antiforschung-Cookies an meine Antworten anzuhängen. Dadurch wurde sichergestellt, dass sie nur generiert wurden, nachdem die MVC-Aktion zurückgegeben wurde.

Controller (Anmerkung: Ich verwalte Benutzer mit ASP.NET Core Identity):

[Authorize]
[ValidateAntiForgeryToken]
public class AccountController : Controller
{
    private SignInManager<IdentityUser> signInManager;
    private UserManager<IdentityUser> userManager;
    private IUserClaimsPrincipalFactory<IdentityUser> userClaimsPrincipalFactory;

    public AccountController(SignInManager<IdentityUser> signInManager, UserManager<IdentityUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> userClaimsPrincipalFactory)
    {
        this.signInManager = signInManager;
        this.userManager = userManager;
        this.userClaimsPrincipalFactory = userClaimsPrincipalFactory;
    }

    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> Login(string username, string password)
    {
        if (username == null || password == null)
        {
            return BadRequest(); // Alias of 400 response
        }

        var result = await signInManager.PasswordSignInAsync(username, password, false, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            var user = await userManager.FindByNameAsync(username);

            // Must manually set the HttpContext user claims to those of the logged
            // in user. Otherwise MVC will still include a XSRF token for the "null"
            // user and token validation will fail. (MVC appends the correct token for
            // all subsequent reponses but this isn't good enough for a single page
            // app.)
            var principal = await userClaimsPrincipalFactory.CreateAsync(user);
            HttpContext.User = principal;

            return Json(new { username = user.UserName });
        }
        else
        {
            return Unauthorized();
        }
    }

    [HttpPost]
    public async Task<IActionResult> Logout()
    {
        await signInManager.SignOutAsync();

        // Removing identity claims manually from the HttpContext (same reason
        // as why we add them manually in the "login" action).
        HttpContext.User = null;

        return Json(new { result = "success" });
    }
}

Ergebnisfilter zum Hinzufügen von Cookies zur Verhinderung von Fälschungen:

public class XSRFCookieFilter : IResultFilter
{
    IAntiforgery antiforgery;

    public XSRFCookieFilter(IAntiforgery antiforgery)
    {
        this.antiforgery = antiforgery;
    }

    public void OnResultExecuting(ResultExecutingContext context)
    {
        var HttpContext = context.HttpContext;
        AntiforgeryTokenSet tokenSet = antiforgery.GetAndStoreTokens(context.HttpContext);
        HttpContext.Response.Cookies.Append(
            "MyXSRFFieldTokenCookieName",
            tokenSet.RequestToken,
            new CookieOptions() {
                // Cookie needs to be accessible to Javascript so we
                // can append it to request headers in the browser
                HttpOnly = false
            } 
        );
    }

    public void OnResultExecuted(ResultExecutedContext context)
    {

    }
}

Startup.cs-Auszug:

public partial class Startup
{
    public Startup(IHostingEnvironment env)
    {
        //...
    }

    public IConfigurationRoot Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {

        //...

        services.AddAntiforgery(options =>
        {
            options.HeaderName = "MyXSRFFieldTokenHeaderName";
        });


        services.AddMvc(options =>
        {
            options.Filters.Add(typeof(XSRFCookieFilter));
        });

        services.AddScoped<XSRFCookieFilter>();

        //...
    }

    public void Configure(
        IApplicationBuilder app,
        IHostingEnvironment env,
        ILoggerFactory loggerFactory)
    {
        //...
    }
}
0
Ned Howley