Anti forgery token jest przeznaczony dla użytkownika"", ale aktualnym użytkownikiem jest " username"

Buduję aplikację jednostronicową i mam problem z tokenami zapobiegającymi fałszowaniu.

Wiem, dlaczego problem się dzieje, po prostu nie wiem, jak go naprawić.

Dostaję błąd, gdy następuje:

    Nie jest to jednak możliwe, ponieważ nie jest to możliwe.]}
  1. użytkownik zamyka okno dialogowe
  2. Użytkownik loguje się
  3. użytkownik otwiera to samo okno dialogowe
  4. użytkownik przesyła formularz w oknie dialogowym

Anty forgery token jest przeznaczony dla użytkownika"", ale obecny użytkownik jest "nazwa użytkownika"

Powodem tak się dzieje jest to, że moja aplikacja jest 100% single-page, a gdy użytkownik pomyślnie loguje się przez Ajax post do /Account/JsonLogin, po prostu przełączyć się bieżące widoki z" uwierzytelnione widoki " zwrócone z serwera, ale {33]} nie przeładowywać strony.

Wiem, że jest to powód, ponieważ jeśli po prostu przeładować stronę między krokami 3 i 4, nie ma błędu.

Więc wygląda na to, że @Html.AntiForgeryToken() w załadowanym formularzu nadal zwraca token dla starego użytkownika, dopóki strona nie zostanie przeładowana.

Jak mogę zmienić @Html.AntiForgeryToken(), aby zwrócić token dla nowego, uwierzytelnionego użytkownika?

I inject a new GenericalPrincipal with a custom IIdentity on every Application_AuthenticateRequest so by the time @Html.AntiForgeryToken() gets called HttpContext.Current.User.Identity is, in factly my custom Identity with IsAuthenticated property set to true, and yet @Html.AntiForgeryToken still seems to rendered a token for the old user unless I do the page reload.

Author: Ahmed, 2013-02-20

10 answers

Dzieje się tak, ponieważ Token zapobiegający fałszowaniu osadza nazwę użytkownika jako część zaszyfrowanego tokenu w celu lepszej walidacji. Po pierwszym wywołaniu @Html.AntiForgeryToken() użytkownik nie jest zalogowany, więc token będzie miał pusty ciąg dla nazwy użytkownika, po zalogowaniu się użytkownika, jeśli nie zastąpisz tokenu zapobiegającego fałszowaniu, nie przejdzie walidacji, ponieważ początkowy token był dla anonimowego użytkownika i teraz mamy uwierzytelnionego użytkownika o znanej nazwie użytkownika.

Masz kilka opcji, aby Rozwiąż ten problem:

  1. Tylko tym razem pozwól swojemu SPA zrobić pełny POST, a gdy Strona się przeładuje, będzie miała token zapobiegający fałszowaniu z wbudowaną zaktualizowaną nazwą użytkownika.

  2. Miej częściowy widok za pomocą tylko @Html.AntiForgeryToken() i zaraz po zalogowaniu wykonaj kolejne żądanie AJAX i zastąp istniejący token zapobiegający fałszowaniu odpowiedzią na żądanie.

  3. Po prostu wyłącz sprawdzanie tożsamości, które wykonuje Walidacja anty-fałszerstwa. Dodaj do swojego Application_Start metoda: AntiForgeryConfig.SuppressIdentityHeuristicChecks = true.

 159
Author: epignosisx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 08:13:33

Aby naprawić błąd, należy umieścić adnotację OutputCache na stronie Get ActionResult logowania jako:

[OutputCache(NoStore=true, Duration = 0, VaryByParam= "None")] 
public ActionResult Login(string returnUrl)
 17
Author: user3401354,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-10 07:12:18

Zdarza się to wiele razy z moją aplikacją, więc postanowiłem ją wygooglować!

Znalazłem proste wyjaśnienie tego błędu! Użytkownik klikając dwukrotnie przycisk logowania! Możesz zobaczyć inny użytkownik mówiący o tym na poniższym linku:

MVC 4 pod warunkiem, że Token anti-forgery był przeznaczony dla użytkownika"", ale aktualnym użytkownikiem jest "user"

Mam nadzieję, że to pomoże! =)

 6
Author: Ricardo França,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-18 18:39:18

Miałem ten sam problem, i ten brudny hack go naprawił, przynajmniej dopóki nie będę mógł naprawić go w czystszy sposób.

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

...

 3
Author: Saúl Jacinto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-19 19:57:03

Miałem dość specyficzny, ale podobny problem w procesie rejestracji. Po kliknięciu łącza e-mail wysłanego do niego, użytkownik zostanie zalogowany i wysłany bezpośrednio do ekranu szczegółów konta, aby podać więcej informacji. Mój kod to:

    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

Odkryłem, że Widok powrotu ("AccountDetails") dawał mi wyjątek token, zgaduję, ponieważ funkcja ConfirmEmail była ozdobiona AllowAnonymous, ale funkcja AccountDetails miała ValidateAntiForgeryToken.

Zmiana Return Na Return RedirectToAction ("AccountDetails") rozwiązała problem.

 1
Author: Liam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-12 11:48:10

Mam ten sam wyjątek występujący najczęściej na serwerze produkcyjnym.

Dlaczego tak się dzieje?

Dzieje się tak, gdy użytkownik loguje się z ważnymi poświadczeniami i po zalogowaniu i przekierowaniu na inną stronę, a po naciśnięciu przycisku Wstecz wyświetli stronę logowania i ponownie wprowadził ważne poświadczenia, że czas ten wyjątek wystąpi.

Jak rozwiązać?

Po prostu dodaj tę linię i pracuj idealnie, Nie uzyskaj błędu.

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
 1
Author: Brijesh Mavani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 12:41:22
[OutputCache(NoStore=true, Duration=0, VaryByParam="None")]

public ActionResult Login(string returnUrl)

Możesz to przetestować, umieszczając punkt przerwania w pierwszej linii działania Login (Get). Przed dodaniem dyrektywy OutputCache punkt przerwania zostanie trafiony przy pierwszym ładowaniu, ale po kliknięciu przycisku Wstecz przeglądarki nie będzie. po dodaniu dyrektywy powinieneś skończyć z punktem przerwania za każdym razem, więc AntiForgeryToken będzie rdzeniem, a nie pustym.

 1
Author: Marian Dalalau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 12:41:52

Miałem ten sam problem z jedną stroną ASP.NET aplikacja MVC Core. Rozwiązałem to ustawiając HttpContext.User we wszystkich akcjach kontrolera, które zmieniają bieżące roszczenia tożsamości (ponieważ MVC robi to tylko dla kolejnych żądań, jak omówiono tutaj). Użyłem filtra wyników zamiast oprogramowania pośredniczącego do dołączania plików cookie do moich odpowiedzi, co upewniło się, że zostały one wygenerowane dopiero po powrocie akcji MVC.

Kontroler (NB. Zarządzam użytkownikami z ASP.NET Rdzeń "Tożsamość": {]}

[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" });
    }
}

Filtr wynikowy do dołączania plików cookie:

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 ekstrakt:

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
Author: Ned Howley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 09:10:18

Wiadomość pojawia się po zalogowaniu, gdy jesteś już uwierzytelniony.

Ten Helper robi dokładnie to samo co atrybut [ValidateAntiForgeryToken].

System.Web.Helpers.AntiForgery.Validate()

Usuń atrybut [ValidateAntiForgeryToken] z kontrolera i umieść ten helper w action methode.

Więc gdy użytkownik jest już uwierzytelniony, przekierować do strony głównej lub jeśli nie kontynuować weryfikację ważnego tokenu anty-forgery po tej weryfikacji.

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

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

Aby spróbować odtworzyć błąd, postępuj jak następuje: Jeśli jesteś na stronie logowania i nie jesteś uwierzytelniony. Jeśli zduplikujesz kartę i logujesz się za pomocą drugiej karty. A jeśli wrócisz do pierwszej Zakładki na stronie logowania i spróbujesz się zalogować bez przeładowywania strony ... masz ten błąd.

 0
Author: A. Morel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 09:17:07

Ma problem z anti-forgery-token validation w sklepie internetowym: użytkownicy otwierają wiele zakładek (z towarami) i po zalogowaniu się na jednym próbują się zalogować na drugim i dostają takie AntiForgeryException. Więc, AntiForgeryConfig.Suppressidentitiheuristicchecks = true nie pomogło mi, więc użyłem takiego brzydkiego hackfixa, może komuś się przyda:

   public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext exceptionContext)
    {
        var exception = exceptionContext.Exception;

        var request = HttpContext.Current.Request;
        if (request != null)
        {
            if (exception is HttpAntiForgeryException &&
                exception.Message.ToLower().StartsWith("the provided anti-forgery token was meant for user \"\", but the current user is"))
            {
                var isAjaxCall = string.Equals("XMLHttpRequest", request.Headers["x-requested-with"], StringComparison.OrdinalIgnoreCase);
                var returnUrl = !string.IsNullOrWhiteSpace(request["returnUrl"]) ? request["returnUrl"] : "/";
                var response = HttpContext.Current.Response;

                if (isAjaxCall)
                {
                    response.Clear();
                    response.StatusCode = 200;
                    response.ContentType = "application/json; charset=utf-8";
                    response.Write(JsonConvert.SerializeObject(new { success = 1, returnUrl = returnUrl }));
                    response.End();
                }
                else
                {
                    response.StatusCode = 200;
                    response.Redirect(returnUrl);
                }
            }
        }


        ExceptionHandler.HandleException(exception);
    }
}

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ExceptionPublisherExceptionFilter());
        filters.Add(new HandleErrorAttribute());
    }
}

Myślę, że będzie świetnie, jeśli Opcje anti-forgery-token generation można ustawić, aby wykluczyć nazwę użytkownika lub coś w tym stylu.

 -3
Author: user3364244,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-28 09:59:47