Cookie Przekierowania podczas logowania są wyłączone dla znanych punktów końcowych API

Domyślnie nieuwierzytelnione i nieautoryzowane żądania wysyłane do znanych punktów końcowych API chronionych przez cookie uwierzytelnianie powodują teraz odpowiedzi 401 i 403, a nie przekierowanie do URI logowania lub odmowy dostępu.

Znane punkty końcowe interfejsu API są identyfikowane przy użyciu nowego IDisableCookieRedirectMetadata interfejsu, a metadane implementowania nowego interfejsu zostały automatycznie dodane do następujących elementów:

  • [ApiController] Punkty końcowe.
  • Minimalne punkty końcowe interfejsu API, które odczytują treści żądań JSON lub zapisują odpowiedzi JSON.
  • Punkty końcowe korzystające z TypedResults typów zwracanych.
  • SignalR Punkty końcowe.

Towarzyszący interfejs IAllowCookieRedirectMetadata ponownie włącza punkt końcowy do przekierowań. Nadpisuje IDisableCookieRedirectMetadata niezależnie od kolejności, w jakiej dodawane są metadane.

Odpowiedzi 401 i 403 nadal zawierają nagłówek Location, który zawiera identyfikator URI logowania lub odmowy dostępu. Zmienia się tylko kod stanu.

Tylko ścieżki uwierzytelnienia (401) i zabronienia dostępu (403) uwzględniają metadane punktu końcowego. Przekierowania po wylogowaniu i przekierowania adresu URL powrotu pozostają bez zmian.

Wersja wprowadzona

.NET 10 (wersja zapoznawcza 7)

Poprzednie zachowanie

cookie Wcześniej program obsługi uwierzytelniania przekierowywał nieuwierzytelnione i nieautoryzowane żądania na stronę logowania lub odmowy dostępu dla wszystkich żądań innych niż XMLHttpRequests (XHRs), domyślnie.

Nowe zachowanie

Począwszy od .NET 10, nieuwierzytelnione i nieautoryzowane żądania wysyłane do znanych punktów końcowych API odpowiadają kodami 401 i 403, zamiast przekierowywania do URI logowania lub odmowy dostępu. Żądania XHR nadal powodują odpowiedzi 401 i 403, niezależnie od docelowego punktu końcowego.

Typ zmiany przełamującej

Ta zmiana jest zmianą behawioralną.

Przyczyna zmiany

Ta zmiana została bardzo żądana. Przekierowywanie nieuwierzytelnionych żądań do strony logowania zwykle nie ma sensu w przypadku punktów końcowych interfejsu API, które zwykle korzystają z kodów stanu 401 i 403, a nie przekierowań HTML do przekazywania błędów uwierzytelniania.

Aby przywrócić poprzednie zachowanie dla całej aplikacji, włącz Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata przełącznik. Cookie uwierzytelnianie ignoruje wtedy metadane punktu końcowego, a tylko żądania XHR skutkują odpowiedziami 401 i 403, co odpowiada zachowaniu sprzed platformy .NET 10. Ustaw przełącznik w pliku projektu, aby był stosowany przed uruchomieniem kodu aplikacji:

<ItemGroup>
  <RuntimeHostConfigurationOption
    Include="Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata"
    Value="true" />
</ItemGroup>

Przełącznik jest odczytywany tylko raz — przy pierwszym użyciu uwierzytelniania cookie — więc jeśli zamiast tego ustawiasz go w kodzie, wywołaj SetSwitch przed skompilowaniem hosta:

AppContext.SetSwitch(
    "Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata", true);

var builder = WebApplication.CreateBuilder(args);

Aby zamiast tego przywrócić przekierowania dla poszczególnych punktów końcowych, wywołaj AllowCookieRedirect lub zastosuj AllowCookieRedirectAttribute do metody akcji lub klasy kontrolera:

app.MapGet("/reports/summary", () => new { Total = 1000 })
   .RequireAuthorization()
   .AllowCookieRedirect();

Z drugiej strony wywołaj metodę DisableCookieRedirect , aby automatycznie zwrócić kody stanu 401 i 403 dla punktów końcowych, które nie są wykrywane jako punkty końcowe interfejsu API.

Jeśli chcesz zawsze przekierowywać do identyfikatorów URI logowania i identyfikatorów URI odmowy dostępu w przypadku nieuwierzytelnionych lub nieautoryzowanych żądań, bez względu na docelowy końcowy punkt, oraz czy źródłem żądania jest XHR, możesz zastąpić RedirectToLogin i RedirectToAccessDenied w następujący sposób:

builder.Services.AddAuthentication()
    .AddCookie(options =>
    {
        options.Events.OnRedirectToLogin = context =>
        {
            context.Response.Redirect(context.RedirectUri);
            return Task.CompletedTask;
        };

        options.Events.OnRedirectToAccessDenied = context =>
        {
            context.Response.Redirect(context.RedirectUri);
            return Task.CompletedTask;
        };
    });

Jeśli chcesz przywrócić dokładnie poprzednie zachowanie, które pozwala uniknąć przekierowań wyłącznie dla XHRów, możesz zastąpić zdarzenia nieco bardziej skomplikowaną logiką:

builder.Services.AddAuthentication()
    .AddCookie(options =>
    {
        bool IsXhr(HttpRequest request)
        {
            return string.Equals(request.Query[HeaderNames.XRequestedWith], "XMLHttpRequest", StringComparison.Ordinal) ||
                string.Equals(request.Headers.XRequestedWith, "XMLHttpRequest", StringComparison.Ordinal);
        }

        options.Events.OnRedirectToLogin = context =>
        {
            if (IsXhr(context.Request))
            {
                context.Response.Headers.Location = context.RedirectUri;
                context.Response.StatusCode = 401;
            }
            else
            {
                context.Response.Redirect(context.RedirectUri);
            }

            return Task.CompletedTask;
        };

        options.Events.OnRedirectToAccessDenied = context =>
        {
            if (IsXhr(context.Request))
            {
                context.Response.Headers.Location = context.RedirectUri;
                context.Response.StatusCode = 403;
            }
            else
            {
                context.Response.Redirect(context.RedirectUri);
            }

            return Task.CompletedTask;
        };
    });

Interfejsy API, których dotyczy problem

Zobacz także