Oprogramowanie pośredniczące platformy ASP.NET Core

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Autorzy: Rick Anderson i Steve Smith

Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:

  • Określa, czy przekazać żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym składniku w potoku.

Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.

Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić śródwierszowo jako metodę anonimową (nazywaną śródwierszowym oprogramowaniem pośredniczącym) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i śródwierszowe metody anonimowe to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywoływanie następnego składnika w potoku lub tworzenie skrótu w potoku. Gdy oprogramowanie pośredniczące tworzy skrót, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.

Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core wyjaśnia różnicę między potokami żądań na platformach ASP.NET Core i ASP.NET 4.x oraz udostępnia dodatkowe przykłady oprogramowania pośredniczącego.

Analiza kodu oprogramowania pośredniczącego

Platforma ASP.NET Core zawiera wiele analizatorów platformy kompilatora, które sprawdzają kod aplikacji pod kątem jakości. Aby uzyskać więcej informacji, zobacz Analiza kodu w aplikacjach platformy ASP.NET Core

Tworzenie potoku oprogramowania pośredniczącego za pomocą polecenia WebApplication

Potok żądania platformy ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Wątek wykonywania przebiega zgodnie z czarnymi strzałkami.

Wzorzec przetwarzania żądania z przedstawionym przychodzącym żądaniem przetwarzanym przez trzy oprogramowania pośredniczące oraz odpowiedzią wychodzącą z aplikacji. Każde oprogramowanie pośredniczące uruchamia własną logikę i przekazuje żądanie do następnego oprogramowania pośredniczącego w instrukcji next(). Gdy trzecie oprogramowanie pośredniczące przetworzy żądanie, żądanie jest przekazywane z powrotem przez dwa poprzednie oprogramowania pośredniczące w odwrotnej kolejności w celu dodatkowego przetworzenia po ich instrukcjach next(), zanim opuści aplikację jako odpowiedź dla klienta.

Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaci obsługujący wyjątki powinni być wywoływani na wczesnym etapie w potoku, aby mogli przechwytywać wyjątki występujące w późniejszych etapach potoku.

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten przypadek nie obejmuje rzeczywistego potoku żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello world!");
});

app.Run();

Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next odzwierciedla następnego delegata w potoku. W potoku można utworzyć skrót przez to, że nie zostanie wywołany parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Do work that can write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.Run();

Zwarcie potoku żądania

Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład oprogramowanie pośredniczące plików statycznych może pełnić rolę końcowego oprogramowania pośredniczącego przez przetwarzanie żądania dla pliku statycznego i tworzenie skrótu w pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Zobacz jednak następujące ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołujej wywołań next.Invoke podczas lub po wysłaniu odpowiedzi do klienta. Po rozpoczęciu HttpResponse zmiany powodują wyjątek. Na przykład ustawienie nagłówków i kodu stanu zgłasza wyjątek po rozpoczęciu odpowiedzi. Zapisywanie w treści odpowiedzi po wywołaniu składnika next:

  • Może spowodować naruszenie protokołu, takie jak zapisanie więcej niż określone Content-Length.
  • Może uszkodzić format treści, taki jak zapisanie stopki HTML w pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy zapisano w treści.

Aby uzyskać więcej informacji, zobacz Oprogramowanie pośredniczące zwarcie po routingu.

Run Delegatów

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym i przerywa potok. Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Do work that can write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.Run();

Jeśli chcesz zobaczyć komentarze kodu przetłumaczone na języki inne niż angielski, poinformuj nas o tym w tym problemie z dyskusją w usłudze GitHub.

W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.

Preferowanie przeciążenia funkcji app.Use, które wymaga przekazania kontekstu do składnika next

Nieprzydzielająca metoda rozszerzenia funkcji app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Zapisuje dwie wewnętrzne alokacje na żądanie, które są wymagane podczas używania innego przeciążenia.

Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.

Kolejność oprogramowania pośredniczącego

Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji są uporządkowane istniejące oprogramowania pośredniczące, oraz gdzie są dodawane niestandardowe oprogramowania pośredniczące. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.

Potok oprogramowania pośredniczącego platformy ASP.NET Core

Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Pages.

Na powyższym diagramie jest przedstawione oprogramowanie pośredniczące Routing, które następuje po oprogramowaniu Pliki statyczne. Jest to kolejność implementowana w szablonach projektów przez jawne wywoływanie funkcji app.UseRouting. Jeśli nie wywołasz funkcji app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku potoku. Aby uzyskać więcej informacji, zobacz Routing.

Potok filtru platformy ASP.NET Core

Kolejność dodawania składników oprogramowania pośredniczącego w pliku Program.cs definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.

Poniższy wyróżniony kod w programie Program.cs dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMiddleware.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
    ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();

app.UseRouting();
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();

app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();

app.MapRazorPages();
app.MapDefaultControllerRoute();

app.Run();

Powyższy kod:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest oznaczone jako komentarz.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład: .
    • Metody UseCors, UseAuthentication i UseAuthorization muszą pojawić się w pokazanej kolejności.
    • Obecnie składnik UseCors musi się pojawić przed składnikiem UseResponseCaching. To wymaganie zostało wyjaśnione w temacie Problem #23218 dotyczący dotnet/aspnetcore w serwisie GitHub.
    • UseRequestLocalization musi pojawić się przed wszelkim oprogramowaniem pośredniczącym, które może sprawdzać kulturę żądania, na przykład app.UseStaticFiles().
    • UseRateLimiter należy wywołać po UseRouting użyciu interfejsów API specyficznych dla punktu końcowego ograniczania szybkości. Jeśli na przykład jest używany atrybut, UseRateLimiter należy wywołać metodę [EnableRateLimiting] po UseRouting. Podczas wywoływania tylko globalnych ograniczników UseRateLimiter można wywołać metodę przed UseRouting.

W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:

app.UseResponseCaching();
app.UseResponseCompression();

W poprzednim kodzie użycie procesora CPU może zostać zmniejszone przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.

Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:

app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();

Poniższy kod Program.cs dodaje składniki oprogramowania pośredniczącego dla typowych scenariuszy aplikacji:

  1. Obsługa wyjątków/błędów
    • Gdy aplikacja jest uruchamiana w środowisku programistycznym:
      • Oprogramowanie pośredniczące strony wyjątku dla deweloperów (UseDeveloperExceptionPage) zgłasza błędy środowiska uruchomieniowego aplikacji.
      • Oprogramowanie pośredniczące strony błędu bazy danych (UseDatabaseErrorPage) zgłasza błędy środowiska uruchomieniowego bazy danych.
    • Gdy aplikacja działa w środowisku produkcyjnym:
      • Oprogramowanie pośredniczące programu obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w następujących oprogramowaniach pośredniczących.
      • Oprogramowanie pośredniczące protokołu HSTS (HTTP Strict Transport Security) (UseHsts) dodaje nagłówek Strict-Transport-Security.
  2. Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
  3. Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i tworzy skrót dla dalszego przetwarzania żądania.
  4. Oprogramowanie pośredniczące zasad dotyczących plików Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z przepisami dotyczącymi ogólnego rozporządzenia o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
  6. Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
  7. Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
  8. Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym zasad dotyczących plików Cookie i przed oprogramowaniem pośredniczącym MVC.
  9. Oprogramowanie pośredniczące routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych produktu Razor Pages do potoku żądania.
if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();

W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku WebApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.

UseExceptionHandler to pierwszy składnik oprogramowania pośredniczącego dodany do potoku. Dlatego oprogramowanie pośredniczące programu obsługi wyjątków przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.

Oprogramowanie pośredniczące plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i tworzyć skrót bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie zapewnia kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.

Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie powoduje tworzenia skrótu dla nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, gdy kontroler MVC wybierze określony produkt Razor Pages lub określonego kontrolera MVC i akcję.

W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi produktu Razor Pages można skompresować.

// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();

app.UseRouting();

app.UseResponseCompression();

app.MapRazorPages();

Aby uzyskać informacje o aplikacjach jednostronicowych, zobacz Omówienie aplikacji jednostronicowych (SPA) w programie ASP.NET Core.

Kolejność składników UseCors i UseStaticFiles

Kolejność wywoływania składników UseCors i UseStaticFiles zależy od aplikacji. Aby uzyskać więcej informacji, zobacz Kolejność składników UseCors i UseStaticFiles

Kolejność oprogramowania pośredniczącego przekazanych nagłówków

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innym oprogramowaniem pośredniczącym. Takie określenie kolejności gwarantuje, że oprogramowanie pośredniczące polegające na informacjach przekazanych nagłówków może zużywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.

Rozgałęzianie potoku oprogramowania pośredniczącego

Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Składnik Map rozgałęzia potok żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1", HandleMapTest1);

app.Map("/map2", HandleMapTest2);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMapTest1(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

static void HandleMapTest2(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 2");
    });
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedzającego kodu.

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/map1 Map Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Hello from non-Map delegate.

Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.

Składnik Map obsługuje zagnieżdżanie, na przykład:

app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        // "/level1/level2a" processing
    });
    level1App.Map("/level2b", level2BApp => {
        // "/level1/level2b" processing
    });
});

Składnik Map może również jednocześnie pasować do wielu segmentów:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1/seg1", HandleMultiSeg);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMultiSeg(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania branch:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleBranch(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        var branchVer = context.Request.Query["branch"];
        await context.Response.WriteAsync($"Branch used = {branchVer}");
    });
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/?branch=main Branch used = main

Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. Inaczej niż w przypadku instrukcji MapWhen ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie tworzy skrótu ani nie zawiera końcowego oprogramowania pośredniczącego:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
    appBuilder => HandleBranchAndRejoin(appBuilder));

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

void HandleBranchAndRejoin(IApplicationBuilder app)
{
    var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>(); 

    app.Use(async (context, next) =>
    {
        var branchVer = context.Request.Query["branch"];
        logger.LogInformation("Branch used = {branchVer}", branchVer);

        // Do work that doesn't write to the Response.
        await next();
        // Do other work that doesn't write to the Response.
    });
}

W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź Hello from non-Map delegate.. Jeśli żądanie zawiera zmienną ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym dołączeniem do potoku głównego.

Wbudowane oprogramowanie pośredniczące

Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order (Kolejność) zawiera uwagi dotyczące umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania i warunki, w których oprogramowanie pośredniczące może przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące tworzy skrót dla potoku przetwarzania żądania i uniemożliwia dalszemu podrzędnemu oprogramowaniu pośredniczącemu przetwarzanie żądania, jest nazywane końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .

Oprogramowanie pośredniczące opis Zamówienie
Authentication Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Końcowe dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Zasady dotyczące plików Cookie Śledzi zgodę użytkowników na przechowywanie danych osobowych i wymusza minimalne standardy dla pól cookie, takie jak secure i SameSite. Przed oprogramowaniem pośredniczącym, które wystawia pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
DeveloperExceptionPage Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym. Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze oprogramowanie pośredniczące w potoku w przypadku środowiska programistycznego.
Diagnostyka Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji. Przed składnikami, które generują błędy. Końcowe dla wyjątków lub obsługujące domyślną stronę internetową dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed składnikami korzystającymi ze zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Rejestrowanie HTTP Rejestruje żądania i odpowiedzi HTTP. Na początku potoku oprogramowania pośredniczącego.
Zastępowanie metody HTTP Zezwala przychodzącemu żądaniu POST na zastępowanie metody. Przed składnikami korzystającymi ze zaktualizowanej metody.
Przekierowywanie HTTPS Przekierowuje wszystkie żądania HTTP do protokołu HTTPS. Przed składnikami korzystającymi z adresu URL.
HTTP Strict Transport Security (HSTS) Oprogramowanie pośredniczące rozszerzenia zabezpieczeń, które dodaje specjalny nagłówek odpowiedzi. Przed wysłaniem odpowiedzi i po składnikach modyfikujących żądania. Przykłady: przekazane nagłówki, ponowne zapisywanie adresu URL.
MVC Przetwarza żądania za pomocą produktu MVC/Razor Pages. Końcowe, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Końcowe, jeśli oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie.
Buforowanie danych wyjściowych Zapewnia obsługę buforowania odpowiedzi na podstawie konfiguracji. Przed składnikami, które wymagają buforowania. Składnik UseRouting musi znajdować się przed składnikiem UseOutputCaching. Składnik UseCORS musi znajdować się przed składnikiem UseOutputCaching.
Buforowanie odpowiedzi Zapewnia obsługę buforowania odpowiedzi. Wymaga to udziału klienta w pracy. Użyj buforowania danych wyjściowych do pełnej kontroli serwera. Przed składnikami, które wymagają buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching. Zazwyczaj nie jest korzystne dla aplikacji interfejsu użytkownika, takich jak Razor Strony, ponieważ przeglądarki zwykle ustawiają nagłówki żądań, które uniemożliwiają buforowanie. Buforowanie danych wyjściowych zapewnia korzyści dla aplikacji interfejsu użytkownika.
Dekompresja żądań Zapewnia obsługę dekompresowania żądań. Przed składnikami odczytującymi treść żądania.
Kompresja odpowiedzi Zapewnia obsługę kompresowania odpowiedzi. Przed składnikami, które wymagają kompresji.
Lokalizacja żądania Zapewnia obsługę lokalizacji. Przed składnikami czułymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Limity czasu żądania Zapewnia obsługę konfigurowania limitów czasu żądania, globalnych i poszczególnych punktów końcowych. UseRequestTimeouts musi znajdować się po UseExceptionHandler, UseDeveloperExceptionPagei UseRouting.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Końcowe dla pasujących tras.
Aplikacja SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowe, jeśli żądanie jest zgodne z plikiem.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
Rejestrowanie W3C Generuje dzienniki dostępu serwera w formacie rozszerzonego pliku dziennika W3C. Na początku potoku oprogramowania pośredniczącego.
Obiekty WebSocket Włącza protokoły WebSocket. Przed składnikami wymaganymi do akceptowania żądań protokołu WebSocket.

Dodatkowe zasoby

Autorzy: Rick Anderson i Steve Smith

Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:

  • Określa, czy przekazać żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym składniku w potoku.

Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.

Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić śródwierszowo jako metodę anonimową (nazywaną śródwierszowym oprogramowaniem pośredniczącym) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i śródwierszowe metody anonimowe to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywoływanie następnego składnika w potoku lub tworzenie skrótu w potoku. Gdy oprogramowanie pośredniczące tworzy skrót, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.

Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core wyjaśnia różnicę między potokami żądań na platformach ASP.NET Core i ASP.NET 4.x oraz udostępnia dodatkowe przykłady oprogramowania pośredniczącego.

Analiza kodu oprogramowania pośredniczącego

Platforma ASP.NET Core zawiera wiele analizatorów platformy kompilatora, które sprawdzają kod aplikacji pod kątem jakości. Aby uzyskać więcej informacji, zobacz Analiza kodu w aplikacjach platformy ASP.NET Core

Tworzenie potoku oprogramowania pośredniczącego za pomocą polecenia WebApplication

Potok żądania platformy ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Wątek wykonywania przebiega zgodnie z czarnymi strzałkami.

Wzorzec przetwarzania żądania z przedstawionym przychodzącym żądaniem przetwarzanym przez trzy oprogramowania pośredniczące oraz odpowiedzią wychodzącą z aplikacji. Każde oprogramowanie pośredniczące uruchamia własną logikę i przekazuje żądanie do następnego oprogramowania pośredniczącego w instrukcji next(). Gdy trzecie oprogramowanie pośredniczące przetworzy żądanie, żądanie jest przekazywane z powrotem przez dwa poprzednie oprogramowania pośredniczące w odwrotnej kolejności w celu dodatkowego przetworzenia po ich instrukcjach next(), zanim opuści aplikację jako odpowiedź dla klienta.

Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaci obsługujący wyjątki powinni być wywoływani na wczesnym etapie w potoku, aby mogli przechwytywać wyjątki występujące w późniejszych etapach potoku.

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten przypadek nie obejmuje rzeczywistego potoku żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello world!");
});

app.Run();

Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next odzwierciedla następnego delegata w potoku. W potoku można utworzyć skrót przez to, że nie zostanie wywołany parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Do work that can write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.Run();

Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład oprogramowanie pośredniczące plików statycznych może pełnić rolę końcowego oprogramowania pośredniczącego przez przetwarzanie żądania dla pliku statycznego i tworzenie skrótu w pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Zobacz jednak następujące ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj składnika next.Invoke po wysłaniu odpowiedzi do klienta. Zmiany wprowadzone w składniku HttpResponse po rozpoczęciu odpowiedzi zgłaszają wyjątek. Na przykład ustawienie nagłówków i kodu stanu zgłasza wyjątek. Zapisywanie w treści odpowiedzi po wywołaniu składnika next:

  • Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
  • Może uszkodzić format treści. Na przykład zapisanie stopki HTML w pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy zapisano w treści.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym i przerywa potok. Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Do work that can write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.Run();

Jeśli chcesz zobaczyć komentarze kodu przetłumaczone na języki inne niż angielski, poinformuj nas o tym w tym problemie z dyskusją w usłudze GitHub.

W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.

Preferowanie przeciążenia funkcji app.Use, które wymaga przekazania kontekstu do składnika next

Nieprzydzielająca metoda rozszerzenia funkcji app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Zapisuje dwie wewnętrzne alokacje na żądanie, które są wymagane podczas używania innego przeciążenia.

Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.

Kolejność oprogramowania pośredniczącego

Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji są uporządkowane istniejące oprogramowania pośredniczące, oraz gdzie są dodawane niestandardowe oprogramowania pośredniczące. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.

Potok oprogramowania pośredniczącego platformy ASP.NET Core

Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Pages.

Na powyższym diagramie jest przedstawione oprogramowanie pośredniczące Routing, które następuje po oprogramowaniu Pliki statyczne. Jest to kolejność implementowana w szablonach projektów przez jawne wywoływanie funkcji app.UseRouting. Jeśli nie wywołasz funkcji app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku potoku. Aby uzyskać więcej informacji, zobacz Routing.

Potok filtru platformy ASP.NET Core

Kolejność dodawania składników oprogramowania pośredniczącego w pliku Program.cs definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.

Poniższy wyróżniony kod w programie Program.cs dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMiddleware.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection")
    ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();

app.UseRouting();
// app.UseRateLimiter();
// app.UseRequestLocalization();
// app.UseCors();

app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();

app.MapRazorPages();
app.MapDefaultControllerRoute();

app.Run();

Powyższy kod:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest oznaczone jako komentarz.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład: .
    • Metody UseCors, UseAuthentication i UseAuthorization muszą pojawić się w pokazanej kolejności.
    • Obecnie składnik UseCors musi się pojawić przed składnikiem UseResponseCaching. To wymaganie zostało wyjaśnione w temacie Problem #23218 dotyczący dotnet/aspnetcore w serwisie GitHub.
    • UseRequestLocalization musi pojawić się przed wszelkim oprogramowaniem pośredniczącym, które może sprawdzać kulturę żądania, na przykład app.UseStaticFiles().
    • UseRateLimiter należy wywołać po UseRouting użyciu interfejsów API specyficznych dla punktu końcowego ograniczania szybkości. Jeśli na przykład jest używany atrybut, UseRateLimiter należy wywołać metodę [EnableRateLimiting] po UseRouting. Podczas wywoływania tylko globalnych ograniczników UseRateLimiter można wywołać metodę przed UseRouting.

W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:

app.UseResponseCaching();
app.UseResponseCompression();

W poprzednim kodzie użycie procesora CPU może zostać zmniejszone przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.

Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:

app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();

Poniższy kod Program.cs dodaje składniki oprogramowania pośredniczącego dla typowych scenariuszy aplikacji:

  1. Obsługa wyjątków/błędów
    • Gdy aplikacja jest uruchamiana w środowisku programistycznym:
      • Oprogramowanie pośredniczące strony wyjątku dla deweloperów (UseDeveloperExceptionPage) zgłasza błędy środowiska uruchomieniowego aplikacji.
      • Oprogramowanie pośredniczące strony błędu bazy danych (UseDatabaseErrorPage) zgłasza błędy środowiska uruchomieniowego bazy danych.
    • Gdy aplikacja działa w środowisku produkcyjnym:
      • Oprogramowanie pośredniczące programu obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w następujących oprogramowaniach pośredniczących.
      • Oprogramowanie pośredniczące protokołu HSTS (HTTP Strict Transport Security) (UseHsts) dodaje nagłówek Strict-Transport-Security.
  2. Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
  3. Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i tworzy skrót dla dalszego przetwarzania żądania.
  4. Oprogramowanie pośredniczące zasad dotyczących plików Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z przepisami dotyczącymi ogólnego rozporządzenia o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
  6. Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
  7. Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
  8. Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym zasad dotyczących plików Cookie i przed oprogramowaniem pośredniczącym MVC.
  9. Oprogramowanie pośredniczące routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych produktu Razor Pages do potoku żądania.
if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();

W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku WebApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.

UseExceptionHandler to pierwszy składnik oprogramowania pośredniczącego dodany do potoku. Dlatego oprogramowanie pośredniczące programu obsługi wyjątków przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.

Oprogramowanie pośredniczące plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i tworzyć skrót bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie zapewnia kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.

Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie powoduje tworzenia skrótu dla nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, gdy kontroler MVC wybierze określony produkt Razor Pages lub określonego kontrolera MVC i akcję.

W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi produktu Razor Pages można skompresować.

// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();

app.UseRouting();

app.UseResponseCompression();

app.MapRazorPages();

Aby uzyskać informacje o aplikacjach jednostronicowych, zobacz przewodniki dotyczące szablonów projektów React i Angular.

Kolejność składników UseCors i UseStaticFiles

Kolejność wywoływania składników UseCors i UseStaticFiles zależy od aplikacji. Aby uzyskać więcej informacji, zobacz Kolejność składników UseCors i UseStaticFiles

Kolejność oprogramowania pośredniczącego przekazanych nagłówków

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innym oprogramowaniem pośredniczącym. Takie określenie kolejności gwarantuje, że oprogramowanie pośredniczące polegające na informacjach przekazanych nagłówków może zużywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.

Rozgałęzianie potoku oprogramowania pośredniczącego

Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Składnik Map rozgałęzia potok żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1", HandleMapTest1);

app.Map("/map2", HandleMapTest2);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMapTest1(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

static void HandleMapTest2(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 2");
    });
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedzającego kodu.

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/map1 Map Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Hello from non-Map delegate.

Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.

Składnik Map obsługuje zagnieżdżanie, na przykład:

app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        // "/level1/level2a" processing
    });
    level1App.Map("/level2b", level2BApp => {
        // "/level1/level2b" processing
    });
});

Składnik Map może również jednocześnie pasować do wielu segmentów:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1/seg1", HandleMultiSeg);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMultiSeg(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania branch:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleBranch(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        var branchVer = context.Request.Query["branch"];
        await context.Response.WriteAsync($"Branch used = {branchVer}");
    });
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/?branch=main Branch used = main

Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. Inaczej niż w przypadku instrukcji MapWhen ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie tworzy skrótu ani nie zawiera końcowego oprogramowania pośredniczącego:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
    appBuilder => HandleBranchAndRejoin(appBuilder));

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

void HandleBranchAndRejoin(IApplicationBuilder app)
{
    var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>(); 

    app.Use(async (context, next) =>
    {
        var branchVer = context.Request.Query["branch"];
        logger.LogInformation("Branch used = {branchVer}", branchVer);

        // Do work that doesn't write to the Response.
        await next();
        // Do other work that doesn't write to the Response.
    });
}

W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź Hello from non-Map delegate.. Jeśli żądanie zawiera zmienną ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym dołączeniem do potoku głównego.

Wbudowane oprogramowanie pośredniczące

Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order (Kolejność) zawiera uwagi dotyczące umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania i warunki, w których oprogramowanie pośredniczące może przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące tworzy skrót dla potoku przetwarzania żądania i uniemożliwia dalszemu podrzędnemu oprogramowaniu pośredniczącemu przetwarzanie żądania, jest nazywane końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .

Oprogramowanie pośredniczące opis Zamówienie
Authentication Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Końcowe dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Zasady dotyczące plików Cookie Śledzi zgodę użytkowników na przechowywanie danych osobowych i wymusza minimalne standardy dla pól cookie, takie jak secure i SameSite. Przed oprogramowaniem pośredniczącym, które wystawia pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
DeveloperExceptionPage Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym. Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze oprogramowanie pośredniczące w potoku w przypadku środowiska programistycznego.
Diagnostyka Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji. Przed składnikami, które generują błędy. Końcowe dla wyjątków lub obsługujące domyślną stronę internetową dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed składnikami korzystającymi ze zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Rejestrowanie HTTP Rejestruje żądania i odpowiedzi HTTP. Na początku potoku oprogramowania pośredniczącego.
Zastępowanie metody HTTP Zezwala przychodzącemu żądaniu POST na zastępowanie metody. Przed składnikami korzystającymi ze zaktualizowanej metody.
Przekierowywanie HTTPS Przekierowuje wszystkie żądania HTTP do protokołu HTTPS. Przed składnikami korzystającymi z adresu URL.
HTTP Strict Transport Security (HSTS) Oprogramowanie pośredniczące rozszerzenia zabezpieczeń, które dodaje specjalny nagłówek odpowiedzi. Przed wysłaniem odpowiedzi i po składnikach modyfikujących żądania. Przykłady: przekazane nagłówki, ponowne zapisywanie adresu URL.
MVC Przetwarza żądania za pomocą produktu MVC/Razor Pages. Końcowe, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Końcowe, jeśli oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie.
Buforowanie danych wyjściowych Zapewnia obsługę buforowania odpowiedzi na podstawie konfiguracji. Przed składnikami, które wymagają buforowania. Składnik UseRouting musi znajdować się przed składnikiem UseOutputCaching. Składnik UseCORS musi znajdować się przed składnikiem UseOutputCaching.
Buforowanie odpowiedzi Zapewnia obsługę buforowania odpowiedzi. Wymaga to udziału klienta w pracy. Użyj buforowania danych wyjściowych do pełnej kontroli serwera. Przed składnikami, które wymagają buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching. Zazwyczaj nie jest korzystne dla aplikacji interfejsu użytkownika, takich jak Razor Strony, ponieważ przeglądarki zwykle ustawiają nagłówki żądań, które uniemożliwiają buforowanie. Buforowanie danych wyjściowych zapewnia korzyści dla aplikacji interfejsu użytkownika.
Dekompresja żądań Zapewnia obsługę dekompresowania żądań. Przed składnikami odczytującymi treść żądania.
Kompresja odpowiedzi Zapewnia obsługę kompresowania odpowiedzi. Przed składnikami, które wymagają kompresji.
Lokalizacja żądania Zapewnia obsługę lokalizacji. Przed składnikami czułymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Końcowe dla pasujących tras.
Aplikacja SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowe, jeśli żądanie jest zgodne z plikiem.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
Rejestrowanie W3C Generuje dzienniki dostępu serwera w formacie rozszerzonego pliku dziennika W3C. Na początku potoku oprogramowania pośredniczącego.
Obiekty WebSocket Włącza protokoły WebSocket. Przed składnikami wymaganymi do akceptowania żądań protokołu WebSocket.

Dodatkowe zasoby

Autorzy: Rick Anderson i Steve Smith

Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:

  • Określa, czy przekazać żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym składniku w potoku.

Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.

Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić śródwierszowo jako metodę anonimową (nazywaną śródwierszowym oprogramowaniem pośredniczącym) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i śródwierszowe metody anonimowe to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywoływanie następnego składnika w potoku lub tworzenie skrótu w potoku. Gdy oprogramowanie pośredniczące tworzy skrót, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.

Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core wyjaśnia różnicę między potokami żądań na platformach ASP.NET Core i ASP.NET 4.x oraz udostępnia dodatkowe przykłady oprogramowania pośredniczącego.

Analiza kodu oprogramowania pośredniczącego

Platforma ASP.NET Core zawiera wiele analizatorów platformy kompilatora, które sprawdzają kod aplikacji pod kątem jakości. Aby uzyskać więcej informacji, zobacz Analiza kodu w aplikacjach platformy ASP.NET Core

Tworzenie potoku oprogramowania pośredniczącego za pomocą polecenia WebApplication

Potok żądania platformy ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Wątek wykonywania przebiega zgodnie z czarnymi strzałkami.

Wzorzec przetwarzania żądania z przedstawionym przychodzącym żądaniem przetwarzanym przez trzy oprogramowania pośredniczące oraz odpowiedzią wychodzącą z aplikacji. Każde oprogramowanie pośredniczące uruchamia własną logikę i przekazuje żądanie do następnego oprogramowania pośredniczącego w instrukcji next(). Gdy trzecie oprogramowanie pośredniczące przetworzy żądanie, żądanie jest przekazywane z powrotem przez dwa poprzednie oprogramowania pośredniczące w odwrotnej kolejności w celu dodatkowego przetworzenia po ich instrukcjach next(), zanim opuści aplikację jako odpowiedź dla klienta.

Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaci obsługujący wyjątki powinni być wywoływani na wczesnym etapie w potoku, aby mogli przechwytywać wyjątki występujące w późniejszych etapach potoku.

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten przypadek nie obejmuje rzeczywistego potoku żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello world!");
});

app.Run();

Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next odzwierciedla następnego delegata w potoku. W potoku można utworzyć skrót przez to, że nie zostanie wywołany parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Do work that can write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.Run();

Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład oprogramowanie pośredniczące plików statycznych może pełnić rolę końcowego oprogramowania pośredniczącego przez przetwarzanie żądania dla pliku statycznego i tworzenie skrótu w pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Zobacz jednak następujące ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj składnika next.Invoke po wysłaniu odpowiedzi do klienta. Zmiany wprowadzone w składniku HttpResponse po rozpoczęciu odpowiedzi zgłaszają wyjątek. Na przykład ustawienie nagłówków i kodu stanu zgłasza wyjątek. Zapisywanie w treści odpowiedzi po wywołaniu składnika next:

  • Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
  • Może uszkodzić format treści. Na przykład zapisanie stopki HTML w pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy zapisano w treści.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym i przerywa potok. Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Use(async (context, next) =>
{
    // Do work that can write to the Response.
    await next.Invoke();
    // Do logging or other work that doesn't write to the Response.
});

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from 2nd delegate.");
});

app.Run();

Jeśli chcesz zobaczyć komentarze kodu przetłumaczone na języki inne niż angielski, poinformuj nas o tym w tym problemie z dyskusją w usłudze GitHub.

W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.

Preferowanie przeciążenia funkcji app.Use, które wymaga przekazania kontekstu do składnika next

Nieprzydzielająca metoda rozszerzenia funkcji app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Zapisuje dwie wewnętrzne alokacje na żądanie, które są wymagane podczas używania innego przeciążenia.

Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.

Kolejność oprogramowania pośredniczącego

Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji są uporządkowane istniejące oprogramowania pośredniczące, oraz gdzie są dodawane niestandardowe oprogramowania pośredniczące. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.

Potok oprogramowania pośredniczącego platformy ASP.NET Core

Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Pages.

Na powyższym diagramie jest przedstawione oprogramowanie pośredniczące Routing, które następuje po oprogramowaniu Pliki statyczne. Jest to kolejność implementowana w szablonach projektów przez jawne wywoływanie funkcji app.UseRouting. Jeśli nie wywołasz funkcji app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku potoku. Aby uzyskać więcej informacji, zobacz Routing.

Potok filtru platformy ASP.NET Core

Kolejność dodawania składników oprogramowania pośredniczącego w pliku Program.cs definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.

Poniższy wyróżniony kod w programie Program.cs dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:

using IndividualAccountsExample.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
// app.UseCookiePolicy();

app.UseRouting();
// app.UseRequestLocalization();
// app.UseCors();

app.UseAuthentication();
app.UseAuthorization();
// app.UseSession();
// app.UseResponseCompression();
// app.UseResponseCaching();

app.MapRazorPages();
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Powyższy kod:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest oznaczone jako komentarz.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład: .
    • Metody UseCors, UseAuthentication i UseAuthorization muszą pojawić się w pokazanej kolejności.
    • Obecnie składnik UseCors musi się pojawić przed składnikiem UseResponseCaching. To wymaganie zostało wyjaśnione w temacie Problem #23218 dotyczący dotnet/aspnetcore w serwisie GitHub.
    • Metoda UseRequestLocalization musi pojawić się przed jakimkolwiek oprogramowaniem pośredniczącym, które może sprawdzić kulturę żądania (na przykład app.UseMvcWithDefaultRoute()).

W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:

app.UseResponseCaching();
app.UseResponseCompression();

W poprzednim kodzie użycie procesora CPU może zostać zmniejszone przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.

Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:

app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();

Poniższy kod Program.cs dodaje składniki oprogramowania pośredniczącego dla typowych scenariuszy aplikacji:

  1. Obsługa wyjątków/błędów
    • Gdy aplikacja jest uruchamiana w środowisku programistycznym:
      • Oprogramowanie pośredniczące strony wyjątku dla deweloperów (UseDeveloperExceptionPage) zgłasza błędy środowiska uruchomieniowego aplikacji.
      • Oprogramowanie pośredniczące strony błędu bazy danych (UseDatabaseErrorPage) zgłasza błędy środowiska uruchomieniowego bazy danych.
    • Gdy aplikacja działa w środowisku produkcyjnym:
      • Oprogramowanie pośredniczące programu obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w następujących oprogramowaniach pośredniczących.
      • Oprogramowanie pośredniczące protokołu HSTS (HTTP Strict Transport Security) (UseHsts) dodaje nagłówek Strict-Transport-Security.
  2. Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
  3. Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i tworzy skrót dla dalszego przetwarzania żądania.
  4. Oprogramowanie pośredniczące zasad dotyczących plików Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z przepisami dotyczącymi ogólnego rozporządzenia o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
  6. Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
  7. Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
  8. Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym zasad dotyczących plików Cookie i przed oprogramowaniem pośredniczącym MVC.
  9. Oprogramowanie pośredniczące routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych produktu Razor Pages do potoku żądania.
if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.MapRazorPages();

W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku WebApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.

UseExceptionHandler to pierwszy składnik oprogramowania pośredniczącego dodany do potoku. Dlatego oprogramowanie pośredniczące programu obsługi wyjątków przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.

Oprogramowanie pośredniczące plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i tworzyć skrót bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie zapewnia kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.

Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie powoduje tworzenia skrótu dla nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, gdy kontroler MVC wybierze określony produkt Razor Pages lub określonego kontrolera MVC i akcję.

W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi produktu Razor Pages można skompresować.

// Static files aren't compressed by Static File Middleware.
app.UseStaticFiles();

app.UseRouting();

app.UseResponseCompression();

app.MapRazorPages();

Aby uzyskać informacje o aplikacjach jednostronicowych, zobacz przewodniki dotyczące szablonów projektów React i Angular.

Kolejność składników UseCors i UseStaticFiles

Kolejność wywoływania składników UseCors i UseStaticFiles zależy od aplikacji. Aby uzyskać więcej informacji, zobacz Kolejność składników UseCors i UseStaticFiles

Kolejność oprogramowania pośredniczącego przekazanych nagłówków

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innym oprogramowaniem pośredniczącym. Takie określenie kolejności gwarantuje, że oprogramowanie pośredniczące polegające na informacjach przekazanych nagłówków może zużywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.

Rozgałęzianie potoku oprogramowania pośredniczącego

Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Składnik Map rozgałęzia potok żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1", HandleMapTest1);

app.Map("/map2", HandleMapTest2);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMapTest1(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

static void HandleMapTest2(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 2");
    });
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedzającego kodu.

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/map1 Map Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Hello from non-Map delegate.

Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.

Składnik Map obsługuje zagnieżdżanie, na przykład:

app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        // "/level1/level2a" processing
    });
    level1App.Map("/level2b", level2BApp => {
        // "/level1/level2b" processing
    });
});

Składnik Map może również jednocześnie pasować do wielu segmentów:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.Map("/map1/seg1", HandleMultiSeg);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleMultiSeg(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        await context.Response.WriteAsync("Map Test 1");
    });
}

Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania branch:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapWhen(context => context.Request.Query.ContainsKey("branch"), HandleBranch);

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

static void HandleBranch(IApplicationBuilder app)
{
    app.Run(async context =>
    {
        var branchVer = context.Request.Query["branch"];
        await context.Response.WriteAsync($"Branch used = {branchVer}");
    });
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/?branch=main Branch used = main

Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. Inaczej niż w przypadku instrukcji MapWhen ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie tworzy skrótu ani nie zawiera końcowego oprogramowania pośredniczącego:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
    appBuilder => HandleBranchAndRejoin(appBuilder));

app.Run(async context =>
{
    await context.Response.WriteAsync("Hello from non-Map delegate.");
});

app.Run();

void HandleBranchAndRejoin(IApplicationBuilder app)
{
    var logger = app.ApplicationServices.GetRequiredService<ILogger<Program>>(); 

    app.Use(async (context, next) =>
    {
        var branchVer = context.Request.Query["branch"];
        logger.LogInformation("Branch used = {branchVer}", branchVer);

        // Do work that doesn't write to the Response.
        await next();
        // Do other work that doesn't write to the Response.
    });
}

W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź Hello from non-Map delegate.. Jeśli żądanie zawiera zmienną ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym dołączeniem do potoku głównego.

Wbudowane oprogramowanie pośredniczące

Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order (Kolejność) zawiera uwagi dotyczące umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania i warunki, w których oprogramowanie pośredniczące może przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące tworzy skrót dla potoku przetwarzania żądania i uniemożliwia dalszemu podrzędnemu oprogramowaniu pośredniczącemu przetwarzanie żądania, jest nazywane końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .

Oprogramowanie pośredniczące opis Zamówienie
Authentication Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Końcowe dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Zasady dotyczące plików Cookie Śledzi zgodę użytkowników na przechowywanie danych osobowych i wymusza minimalne standardy dla pól cookie, takie jak secure i SameSite. Przed oprogramowaniem pośredniczącym, które wystawia pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
DeveloperExceptionPage Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym. Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze oprogramowanie pośredniczące w potoku w przypadku środowiska programistycznego.
Diagnostyka Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji. Przed składnikami, które generują błędy. Końcowe dla wyjątków lub obsługujące domyślną stronę internetową dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed składnikami korzystającymi ze zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Rejestrowanie HTTP Rejestruje żądania i odpowiedzi HTTP. Na początku potoku oprogramowania pośredniczącego.
Zastępowanie metody HTTP Zezwala przychodzącemu żądaniu POST na zastępowanie metody. Przed składnikami korzystającymi ze zaktualizowanej metody.
Przekierowywanie HTTPS Przekierowuje wszystkie żądania HTTP do protokołu HTTPS. Przed składnikami korzystającymi z adresu URL.
HTTP Strict Transport Security (HSTS) Oprogramowanie pośredniczące rozszerzenia zabezpieczeń, które dodaje specjalny nagłówek odpowiedzi. Przed wysłaniem odpowiedzi i po składnikach modyfikujących żądania. Przykłady: przekazane nagłówki, ponowne zapisywanie adresu URL.
MVC Przetwarza żądania za pomocą produktu MVC/Razor Pages. Końcowe, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Końcowe, jeśli oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie.
Dekompresja żądań Zapewnia obsługę dekompresowania żądań. Przed składnikami odczytującymi treść żądania.
Buforowanie odpowiedzi Zapewnia obsługę buforowania odpowiedzi. Przed składnikami, które wymagają buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching.
Kompresja odpowiedzi Zapewnia obsługę kompresowania odpowiedzi. Przed składnikami, które wymagają kompresji.
Lokalizacja żądania Zapewnia obsługę lokalizacji. Przed składnikami czułymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Końcowe dla pasujących tras.
Aplikacja SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowe, jeśli żądanie jest zgodne z plikiem.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
Rejestrowanie W3C Generuje dzienniki dostępu serwera w formacie rozszerzonego pliku dziennika W3C. Na początku potoku oprogramowania pośredniczącego.
Obiekty WebSocket Włącza protokoły WebSocket. Przed składnikami wymaganymi do akceptowania żądań protokołu WebSocket.

Dodatkowe zasoby

Autorzy: Rick Anderson i Steve Smith

Oprogramowanie pośredniczące to oprogramowanie, które jest wmontowane w potok aplikacji w celu obsługi żądań i odpowiedzi. Każdy składnik:

  • Określa, czy przekazać żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym składniku w potoku.

Delegaci żądań są używani do kompilowania potoku żądania. Delegaci żądań obsługują każde żądanie HTTP.

Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić śródwierszowo jako metodę anonimową (nazywaną śródwierszowym oprogramowaniem pośredniczącym) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i śródwierszowe metody anonimowe to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywoływanie następnego składnika w potoku lub tworzenie skrótu w potoku. Gdy oprogramowanie pośredniczące tworzy skrót, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.

Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core wyjaśnia różnicę między potokami żądań na platformach ASP.NET Core i ASP.NET 4.x oraz udostępnia dodatkowe przykłady oprogramowania pośredniczącego.

Tworzenie potoku oprogramowania pośredniczącego przy użyciu programu IApplicationBuilder

Potok żądania platformy ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Wątek wykonywania przebiega zgodnie z czarnymi strzałkami.

Wzorzec przetwarzania żądania z przedstawionym przychodzącym żądaniem przetwarzanym przez trzy oprogramowania pośredniczące oraz odpowiedzią wychodzącą z aplikacji. Każde oprogramowanie pośredniczące uruchamia własną logikę i przekazuje żądanie do następnego oprogramowania pośredniczącego w instrukcji next(). Gdy trzecie oprogramowanie pośredniczące przetworzy żądanie, żądanie jest przekazywane z powrotem przez dwa poprzednie oprogramowania pośredniczące w odwrotnej kolejności w celu dodatkowego przetworzenia po ich instrukcjach next(), zanim opuści aplikację jako odpowiedź dla klienta.

Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaci obsługujący wyjątki powinni być wywoływani na wczesnym etapie w potoku, aby mogli przechwytywać wyjątki występujące w późniejszych etapach potoku.

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten przypadek nie obejmuje rzeczywistego potoku żądania. Zamiast tego w odpowiedzi na każde żądanie HTTP jest wywoływana jedna funkcja anonimowa.

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello, World!");
        });
    }
}

Połącz wiele delegatów żądań razem za pomocą funkcji Use. Parametr next odzwierciedla następnego delegata w potoku. W potoku można utworzyć skrót przez to, że nie zostanie wywołany parametr next. Zazwyczaj można wykonywać akcje zarówno przed następnym delegatem, jak i po nim, jak pokazano w poniższym przykładzie:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład oprogramowanie pośredniczące plików statycznych może pełnić rolę końcowego oprogramowania pośredniczącego przez przetwarzanie żądania dla pliku statycznego i tworzenie skrótu w pozostałej części potoku. Oprogramowanie pośredniczące dodane do potoku przed oprogramowaniem pośredniczącym, które przerywa dalsze przetwarzanie, nadal przetwarza kod po instrukcjach next.Invoke. Zobacz jednak następujące ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj składnika next.Invoke po wysłaniu odpowiedzi do klienta. Zmiany wprowadzone w składniku HttpResponse po rozpoczęciu odpowiedzi zgłaszają wyjątek. Na przykład ustawienie nagłówków i kodu stanu zgłasza wyjątek. Zapisywanie w treści odpowiedzi po wywołaniu składnika next:

  • Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
  • Może uszkodzić format treści. Na przykład zapisanie stopki HTML w pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub czy zapisano w treści.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym i przerywa potok. Run to konwencja. Niektóre składniki oprogramowania pośredniczącego mogą uwidaczniać metody Run[Middleware] uruchamiane na końcu potoku:

public class Startup
{
    public void Configure(IApplicationBuilder app)
    {
        app.Use(async (context, next) =>
        {
            // Do work that doesn't write to the Response.
            await next.Invoke();
            // Do logging or other work that doesn't write to the Response.
        });

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from 2nd delegate.");
        });
    }
}

Jeśli chcesz zobaczyć komentarze kodu przetłumaczone na języki inne niż angielski, poinformuj nas o tym w tym problemie z dyskusją w usłudze GitHub.

W poprzednim przykładzie delegat Run zapisuje "Hello from 2nd delegate." w odpowiedzi, a następnie przerywa potok. Jeśli inny delegat Use lub Run zostanie dodany po delegacie Run, nie będzie on wywoływany.

Kolejność oprogramowania pośredniczącego

Na poniższym diagramie przedstawiono kompletny potok przetwarzania żądania dla aplikacji MVC i Razor Pages na platformie ASP.NET Core. Można zobaczyć, jak w typowej aplikacji są uporządkowane istniejące oprogramowania pośredniczące, oraz gdzie są dodawane niestandardowe oprogramowania pośredniczące. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.

Potok oprogramowania pośredniczącego platformy ASP.NET Core

Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Pages.

Potok filtru platformy ASP.NET Core

Kolejność dodawania składników oprogramowania pośredniczącego w metodzie Startup.Configure definiuje kolejność wywoływania składników oprogramowania pośredniczącego w żądaniach oraz odwrotną kolejność dla odpowiedzi. Kolejność ma kluczowe znaczenie dla bezpieczeństwa, wydajności i funkcjonalności.

Poniższa metoda Startup.Configure dodaje składniki oprogramowania pośredniczącego związane z zabezpieczeniami w typowej zalecanej kolejności:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    // app.UseCookiePolicy();

    app.UseRouting();
    // app.UseRequestLocalization();
    // app.UseCors();

    app.UseAuthentication();
    app.UseAuthorization();
    // app.UseSession();
    // app.UseResponseCompression();
    // app.UseResponseCaching();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Powyższy kod:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest oznaczone jako komentarz.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład: .
    • Metody UseCors, UseAuthentication i UseAuthorization muszą pojawić się w pokazanej kolejności.
    • Obecnie składnik UseCors musi pojawiać się przed składnikiem UseResponseCaching z powodu tej usterki.
    • Metoda UseRequestLocalization musi pojawić się przed jakimkolwiek oprogramowaniem pośredniczącym, które może sprawdzić kulturę żądania (na przykład app.UseMvcWithDefaultRoute()).

W niektórych scenariuszach oprogramowanie pośredniczące ma inne określanie kolejności. Na przykład określanie kolejności buforowania i kompresji jest specyficzne dla scenariusza i istnieje wiele prawidłowych określeń kolejności. Na przykład:

app.UseResponseCaching();
app.UseResponseCompression();

W poprzednim kodzie można oszczędzać zasoby procesora CPU przez buforowanie skompresowanej odpowiedzi, ale może to doprowadzić do buforowania wielu reprezentacji zasobu przy użyciu różnych algorytmów kompresji, takich jak Gzip lub Brotli.

Poniższe określanie kolejności łączy pliki statyczne w celu umożliwienia buforowania skompresowanych plików statycznych:

app.UseResponseCaching();
app.UseResponseCompression();
app.UseStaticFiles();

Poniższa metoda Startup.Configure dodaje składniki oprogramowania pośredniczącego dla typowych scenariuszy aplikacji:

  1. Obsługa wyjątków/błędów
    • Gdy aplikacja jest uruchamiana w środowisku programistycznym:
      • Oprogramowanie pośredniczące strony wyjątku dla deweloperów (UseDeveloperExceptionPage) zgłasza błędy środowiska uruchomieniowego aplikacji.
      • Oprogramowanie pośredniczące strony błędu bazy danych zgłasza błędy środowiska uruchomieniowego bazy danych.
    • Gdy aplikacja działa w środowisku produkcyjnym:
      • Oprogramowanie pośredniczące programu obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w następujących oprogramowaniach pośredniczących.
      • Oprogramowanie pośredniczące protokołu HSTS (HTTP Strict Transport Security) (UseHsts) dodaje nagłówek Strict-Transport-Security.
  2. Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
  3. Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i tworzy skrót dla dalszego przetwarzania żądania.
  4. Oprogramowanie pośredniczące zasad dotyczących plików Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z przepisami dotyczącymi ogólnego rozporządzenia o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
  6. Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
  7. Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
  8. Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym zasad dotyczących plików Cookie i przed oprogramowaniem pośredniczącym MVC.
  9. Oprogramowanie pośredniczące routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych produktu Razor Pages do potoku żądania.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseCookiePolicy();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseSession();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

W poprzednim kodzie przykładowym każda metoda rozszerzenia oprogramowania pośredniczącego jest uwidoczniona w składniku IApplicationBuilder za pośrednictwem przestrzeni nazw Microsoft.AspNetCore.Builder.

UseExceptionHandler to pierwszy składnik oprogramowania pośredniczącego dodany do potoku. Dlatego oprogramowanie pośredniczące programu obsługi wyjątków przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.

Oprogramowanie pośredniczące plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i tworzyć skrót bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie zapewnia kontroli autoryzacji. Wszystkie pliki obsługiwane przez oprogramowanie pośredniczące plików statycznych, w tym te w katalogu wwwroot, są publicznie dostępne. Aby poznać metodę zabezpieczania plików statycznych, zobacz Pliki statyczne na platformie ASP.NET Core.

Jeśli żądanie nie jest obsługiwane przez oprogramowanie pośredniczące plików statycznych, jest przekazywane do oprogramowania pośredniczącego uwierzytelniania (UseAuthentication), które wykonuje uwierzytelnianie. Uwierzytelnianie nie powoduje tworzenia skrótu dla nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, gdy kontroler MVC wybierze określony produkt Razor Pages lub określonego kontrolera MVC i akcję.

W poniższym przykładzie pokazano kolejność oprogramowania pośredniczącego, w której żądania dotyczące plików statycznych są obsługiwane przez oprogramowanie pośredniczące plików statycznych przed oprogramowaniem pośredniczącym kompresji odpowiedzi. Pliki statyczne nie są kompresowane w ramach tej kolejności oprogramowania pośredniczącego. Odpowiedzi produktu Razor Pages można skompresować.

public void Configure(IApplicationBuilder app)
{
    // Static files aren't compressed by Static File Middleware.
    app.UseStaticFiles();

    app.UseRouting();

    app.UseResponseCompression();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

W przypadku aplikacji jednostronicowych (SPA) oprogramowanie pośredniczące aplikacji SPA UseSpaStaticFiles zwykle jest ostatnie w potoku oprogramowania pośredniczącego. Oprogramowanie pośredniczące aplikacji SPA jest ostatnie:

  • Aby umożliwić wszystkim innym oprogramowaniom pośredniczącym na reagowanie na pasujące żądania w pierwszej kolejności.
  • Aby umożliwić uruchamianie aplikacji SPA z routingiem po stronie klienta dla wszystkich tras, które są nierozpoznane przez aplikację serwera.

Aby uzyskać więcej szczegółowych informacji dotyczących aplikacji SPA, zobacz przewodniki dotyczące szablonów projektów React i Angular.

Kolejność oprogramowania pośredniczącego przekazanych nagłówków

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innym oprogramowaniem pośredniczącym. Takie określenie kolejności gwarantuje, że oprogramowanie pośredniczące polegające na informacjach przekazanych nagłówków może zużywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.

Rozgałęzianie potoku oprogramowania pośredniczącego

Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Składnik Map rozgałęzia potok żądania na podstawie dopasowań podanej ścieżki żądania. Jeśli ścieżka żądania rozpoczyna się od podanej ścieżki, wykonywane jest rozgałęzianie.

public class Startup
{
    private static void HandleMapTest1(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 1");
        });
    }

    private static void HandleMapTest2(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map Test 2");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1", HandleMapTest1);

        app.Map("/map2", HandleMapTest2);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate.");
        });
    }
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu.

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/map1 Map Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Hello from non-Map delegate.

Gdy jest używany składnik Map, dopasowane segmenty ścieżki są usuwane ze składnika HttpRequest.Path i dołączane do składnika HttpRequest.PathBase dla każdego żądania.

Składnik Map obsługuje zagnieżdżanie, na przykład:

app.Map("/level1", level1App => {
    level1App.Map("/level2a", level2AApp => {
        // "/level1/level2a" processing
    });
    level1App.Map("/level2b", level2BApp => {
        // "/level1/level2b" processing
    });
});

Składnik Map może również jednocześnie pasować do wielu segmentów:

public class Startup
{
    private static void HandleMultiSeg(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Map multiple segments.");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.Map("/map1/seg1", HandleMultiSeg);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate.");
        });
    }
}

Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź potoku. W poniższym przykładzie predykat jest używany do wykrywania obecności zmiennej ciągu zapytania branch:

public class Startup
{
    private static void HandleBranch(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            var branchVer = context.Request.Query["branch"];
            await context.Response.WriteAsync($"Branch used = {branchVer}");
        });
    }

    public void Configure(IApplicationBuilder app)
    {
        app.MapWhen(context => context.Request.Query.ContainsKey("branch"),
                               HandleBranch);

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from non-Map delegate.");
        });
    }
}

W poniższej tabeli przedstawiono żądania i odpowiedzi z adresu http://localhost:1234 przy użyciu poprzedniego kodu:

Zażądaj Response
localhost:1234 Hello from non-Map delegate.
localhost:1234/?branch=main Branch used = main

Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. Inaczej niż w przypadku instrukcji MapWhen ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie tworzy skrótu ani nie zawiera końcowego oprogramowania pośredniczącego:

public class Startup
{
    private void HandleBranchAndRejoin(IApplicationBuilder app, ILogger<Startup> logger)
    {
        app.Use(async (context, next) =>
        {
            var branchVer = context.Request.Query["branch"];
            logger.LogInformation("Branch used = {branchVer}", branchVer);

            // Do work that doesn't write to the Response.
            await next();
            // Do other work that doesn't write to the Response.
        });
    }

    public void Configure(IApplicationBuilder app, ILogger<Startup> logger)
    {
        app.UseWhen(context => context.Request.Query.ContainsKey("branch"),
                               appBuilder => HandleBranchAndRejoin(appBuilder, logger));

        app.Run(async context =>
        {
            await context.Response.WriteAsync("Hello from main pipeline.");
        });
    }
}

W poprzednim przykładzie dla wszystkich żądań jest pisana odpowiedź „Hello from main pipeline” (Pozdrowienia od głównego potoku). Jeśli żądanie zawiera zmienną ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym dołączeniem do potoku głównego.

Wbudowane oprogramowanie pośredniczące

Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order (Kolejność) zawiera uwagi dotyczące umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania i warunki, w których oprogramowanie pośredniczące może przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące tworzy skrót dla potoku przetwarzania żądania i uniemożliwia dalszemu podrzędnemu oprogramowaniu pośredniczącemu przetwarzanie żądania, jest nazywane końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat tworzenia skrótów, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego przy użyciu programu IApplicationBuilder.

Oprogramowanie pośredniczące opis Zamówienie
Authentication Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Końcowe dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Zasady dotyczące plików Cookie Śledzi zgodę użytkowników na przechowywanie danych osobowych i wymusza minimalne standardy dla pól cookie, takie jak secure i SameSite. Przed oprogramowaniem pośredniczącym, które wystawia pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
Diagnostyka Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji. Przed składnikami, które generują błędy. Końcowe dla wyjątków lub obsługujące domyślną stronę internetową dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed składnikami korzystającymi ze zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Zastępowanie metody HTTP Zezwala przychodzącemu żądaniu POST na zastępowanie metody. Przed składnikami korzystającymi ze zaktualizowanej metody.
Przekierowywanie HTTPS Przekierowuje wszystkie żądania HTTP do protokołu HTTPS. Przed składnikami korzystającymi z adresu URL.
HTTP Strict Transport Security (HSTS) Oprogramowanie pośredniczące rozszerzenia zabezpieczeń, które dodaje specjalny nagłówek odpowiedzi. Przed wysłaniem odpowiedzi i po składnikach modyfikujących żądania. Przykłady: przekazane nagłówki, ponowne zapisywanie adresu URL.
MVC Przetwarza żądania za pomocą produktu MVC/Razor Pages. Końcowe, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Końcowe, jeśli oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie.
Buforowanie odpowiedzi Zapewnia obsługę buforowania odpowiedzi. Przed składnikami, które wymagają buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching.
Kompresja odpowiedzi Zapewnia obsługę kompresowania odpowiedzi. Przed składnikami, które wymagają kompresji.
Lokalizacja żądania Zapewnia obsługę lokalizacji. Przed składnikami czułymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Końcowe dla pasujących tras.
Aplikacja SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowe, jeśli żądanie jest zgodne z plikiem.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
Obiekty WebSocket Włącza protokół WebSocket. Przed składnikami wymaganymi do akceptowania żądań protokołu WebSocket.

Dodatkowe zasoby