Udostępnij za pośrednictwem


Oprogramowanie pośredniczące platformy ASP.NET Core

Uwaga

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

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz zasady pomocy technicznej platformy .NET i platformy .NET Core. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu .NET 9.

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ą, zobacz wersję tego artykułu .NET 9.

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ć dalej żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym elemencie w przepływie pracy.

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 anonimowe funkcje w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy komponent pośredniczący w potoku żądania jest odpowiedzialny za wywoływanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu żądania przez oprogramowanie pośredniczące.

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

Rola oprogramowania pośredniczącego według typu aplikacji

Blazor Web Apps, Razor Pages oraz MVC przetwarzają żądania przeglądarki na serwerze przy użyciu middleware. Wskazówki zawarte w tym artykule dotyczą tych typów aplikacji.

Autonomiczne aplikacje Blazor WebAssembly są uruchamiane w całości na kliencie i nie przetwarzają żądań przy użyciu kanału oprogramowania pośredniczącego. Wskazówki zawarte w tym artykule nie dotyczą autonomicznych aplikacji Blazor WebAssembly.

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

Utwórz potok oprogramowania pośredniczącego za pomocą WebApplication

Potok przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań, wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Przebieg 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. Ta sytuacja nie obejmuje rzeczywistego potoku przetwarzania żą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 reprezentuje następnego delegata w potoku. Można przerwać działanie potoku, nie wywołując 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 przerywaniem potoku żądania. Krótkie zwarcie jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie 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. Niemniej jednak, zapoznaj się z następującym ostrzeżeniem dotyczącym próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj next.Invoke podczas lub po wysłaniu odpowiedzi do klienta. Po rozpoczęciu HttpResponse, wszelkie 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 komponentu next:

  • Może spowodować naruszenie protokołu, na przykład zapisanie większej ilości niż przewidziano 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 treść została zapisana.

Aby uzyskać więcej informacji, zobacz oprogramowanie pośredniczące krótkiego sprzężenia po routingu.

Run Delegatów

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i kończy 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.

Preferuj przeciążenie app.Use, które wymaga przekazania kontekstu do parametru 'next'

Metoda rozszerzenia nieprzydzielająca zasobów app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Eliminuje dwie wewnętrzne alokacje per-request, które są konieczne podczas korzystania z innego wariantu 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 uporządkowane są istniejące middleware oraz gdzie dodaje się niestandardowe middleware. 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 middlewarowe punktu końcowego na wcześniejszym diagramie wykonuje przepływ filtracyjny dla odpowiedniego typu aplikacji — MVC lub Razor Strony.

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 app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku procesu. 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();

W poprzednim kodzie:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
    • 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. Na przykład, jeśli używany jest atrybut [EnableRateLimiting], UseRateLimiter musi być wywołany po UseRouting. Podczas wywoływania tylko globalnych ograniczników, UseRateLimiter można wywołać 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:
      • Strona wyjątków dla programistów (Middleware) (UseDeveloperExceptionPage) zgłasza błędy wykonania 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 obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w kolejnych pośrednikach.
      • Oprogramowanie pośredniczące protokołu HTTP Strict Transport Security (HSTS) (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 przerywa dalsze przetwarzanie żądania.
  4. Polityka Middleware (Cookie) (UseCookiePolicy) zapewnia zgodność aplikacji z rozporządzeniem o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące do routingu (UseRouting) do trasowania żą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 do routingu punktów końcowych (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych 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 też oprogramowanie pośredniczące obsługi wyjątków przechwytuje wszelkie wyjątki, które występują w późniejszych wywołaniach.

Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, aby mogło obsługiwać żądania i przerywać ich przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie przeprowadza 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 przerywa żądań nieuwierzytelnionych. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybierze określoną stronę Razor lub kontroler 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 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ść UseCors i UseStaticFiles

Kolejność modułu "Forwarded Headers Middleware"

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innymi oprogramowaniami pośredniczącymi. Ustalenie tej kolejności gwarantuje, że middleware opierające się na informacjach z przekazanych nagłówków może korzystać z 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 kanału oprogramowania pośredniego

Rozszerzenia Map są używane jako standard do rozgałęziania procesu. Element 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 Odpowiedź
localhost:1234 Witaj od delegata nie-Mapy.
localhost:1234/map1 Test mapy 1
localhost:1234/map2 Test mapy 2
localhost:1234/map3 Witaj od delegata nie-Mapy.

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.

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

MapWhen rozgałęzia potok żądania w oparciu o wynik 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 Odpowiedź
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. W przeciwieństwie do MapWhen, ta gałąź jest ponownie łączona do głównej rury, jeśli nie zawiera middleware terminalnego.

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ą parametru 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 zawiera uwagi na temat umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunki, w których może ono przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia innemu oprogramowaniu pośredniczącemu dalsze przetwarzanie żądania, nazywane jest 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
Antyfałszerstwo Zapewnia obsługę ochrony przed fałszowaniem żądań. Po uwierzytelnieniu i autoryzacji przed punktami końcowymi.
Uwierzytelnianie Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Terminal dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Cookie Polityka Ś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 wydaje pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
MECHANIZM 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 pierwszy komponent w potoku, gdy środowisko to Deweloperskie.
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. Terminal obsługujący wyjątki lub 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. Zakończ, jeśli żądanie pasuje do punktu końcowego kontroli stanu zdrowia.
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 łańcucha 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 do zwiększania 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ńcowy, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Terminalne, jeśli oprogramowanie pośredniczące OWIN przetwarza w pełni żą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 komponentami wrażliwymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Upłynięcie limitu 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ń. Terminal do dopasowywania tras.
UZDROWISKO Obsługuje wszystkie żądania od tego punktu w łańcuchu middleware, zwracając domyślną stronę dla Single Page Application (SPA). Na końcu łańcucha, aby inne oprogramowanie pośredniczące, które obsługuje pliki statyczne, akcje MVC itp., miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji użytkownika.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Zakończ, jeśli żądanie pasuje do pliku.
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 łańcucha oprogramowania pośredniczącego.
WebSockety 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ć dalej żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym elemencie w przepływie pracy.

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 anonimowe funkcje w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy komponent pośredniczący w potoku żądania jest odpowiedzialny za wywoływanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu żądania przez oprogramowanie pośredniczące.

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

Rola oprogramowania pośredniczącego według typu aplikacji

Razor Pages, MVC, Blazor Server, i przetwarzanie żądań przeglądarki przez projekt serwera hostowanego Blazor WebAssembly rozwiązania na serwerze z użyciem oprogramowania pośredniczącego. Wskazówki zawarte w tym artykule dotyczą tych typów aplikacji.

Autonomiczne aplikacje Blazor WebAssembly są uruchamiane w całości na kliencie i nie przetwarzają żądań przy użyciu kanału oprogramowania pośredniczącego. Wskazówki zawarte w tym artykule nie dotyczą autonomicznych aplikacji Blazor WebAssembly.

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

Utwórz potok oprogramowania pośredniczącego za pomocą WebApplication

Potok przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań, wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Przebieg 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. Ta sytuacja nie obejmuje rzeczywistego potoku przetwarzania żą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 reprezentuje następnego delegata w potoku. Można przerwać działanie potoku, nie wywołując 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 przerywaniem potoku żądania. Krótkie zwarcie jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie 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. Niemniej jednak, zapoznaj się z następującym ostrzeżeniem dotyczącym próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj elementu next.Invoke po tym, jak odpowiedź została wysłana 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 powoduje zgłoszenie wyjątku. Zapisywanie w treści odpowiedzi po wywołaniu komponentu 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 ciała. Na przykład zapisanie stopki HTML do pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub treść została zapisana.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i kończy 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.

Preferuj przeciążenie app.Use, które wymaga przekazania kontekstu do parametru 'next'

Metoda rozszerzenia nieprzydzielająca zasobów app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Eliminuje dwie wewnętrzne alokacje per-request, które są konieczne podczas korzystania z innego wariantu 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 uporządkowane są istniejące middleware oraz gdzie dodaje się niestandardowe middleware. 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 middlewarowe punktu końcowego na wcześniejszym diagramie wykonuje przepływ filtracyjny dla odpowiedniego typu aplikacji — MVC lub Razor Strony.

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 app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku procesu. 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();

W poprzednim kodzie:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
    • 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. Na przykład, jeśli używany jest atrybut [EnableRateLimiting], UseRateLimiter musi być wywołany po UseRouting. Podczas wywoływania tylko globalnych ograniczników, UseRateLimiter można wywołać 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:
      • Strona wyjątków dla programistów (Middleware) (UseDeveloperExceptionPage) zgłasza błędy wykonania 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 obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w kolejnych pośrednikach.
      • Oprogramowanie pośredniczące protokołu HTTP Strict Transport Security (HSTS) (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 przerywa dalsze przetwarzanie żądania.
  4. Polityka Middleware (Cookie) (UseCookiePolicy) zapewnia zgodność aplikacji z rozporządzeniem o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące do routingu (UseRouting) do trasowania żą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 do routingu punktów końcowych (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych 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 też oprogramowanie pośredniczące obsługi wyjątków przechwytuje wszelkie wyjątki, które występują w późniejszych wywołaniach.

Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, aby mogło obsługiwać żądania i przerywać ich przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie przeprowadza 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 przerywa żądań nieuwierzytelnionych. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybierze określoną stronę Razor lub kontroler 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 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ść UseCors i UseStaticFiles

Kolejność modułu "Forwarded Headers Middleware"

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innymi oprogramowaniami pośredniczącymi. Ustalenie tej kolejności gwarantuje, że middleware opierające się na informacjach z przekazanych nagłówków może korzystać z 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 kanału oprogramowania pośredniego

Rozszerzenia Map są używane jako standard do rozgałęziania procesu. Element 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 Odpowiedź
localhost:1234 Witaj od delegata nie-Mapy.
localhost:1234/map1 Test mapy 1
localhost:1234/map2 Test mapy 2
localhost:1234/map3 Witaj od delegata nie-Mapy.

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.

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

MapWhen rozgałęzia potok żądania w oparciu o wynik 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 Odpowiedź
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. W przeciwieństwie do MapWhen, ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie przerywa działania 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ą parametru 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 zawiera uwagi na temat umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunki, w których może ono przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia innemu oprogramowaniu pośredniczącemu dalsze przetwarzanie żądania, nazywane jest 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
Uwierzytelnianie Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Terminal dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Cookie Polityka Ś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 wydaje pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
MECHANIZM 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 pierwszy komponent w potoku, gdy środowisko to Deweloperskie.
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. Terminal obsługujący wyjątki lub 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. Zakończ, jeśli żądanie pasuje do punktu końcowego kontroli stanu zdrowia.
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 łańcucha 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 do zwiększania 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ńcowy, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Terminalne, jeśli oprogramowanie pośredniczące OWIN przetwarza w pełni żą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 komponentami wrażliwymi 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ń. Terminal do dopasowywania tras.
UZDROWISKO Obsługuje wszystkie żądania od tego punktu w łańcuchu middleware, zwracając domyślną stronę dla Single Page Application (SPA). Na końcu łańcucha, aby inne oprogramowanie pośredniczące, które obsługuje pliki statyczne, akcje MVC itp., miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji użytkownika.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Zakończ, jeśli żądanie pasuje do pliku.
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 łańcucha oprogramowania pośredniczącego.
WebSockety 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ć dalej żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym elemencie w przepływie pracy.

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 anonimowe funkcje w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy komponent pośredniczący w potoku żądania jest odpowiedzialny za wywoływanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu żądania przez oprogramowanie pośredniczące.

Migrowanie modułów HTTP do oprogramowania pośredniczącego ASP.NET Core wyjaśnia różnicę między potokami żądań w 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

Utwórz potok oprogramowania pośredniczącego za pomocą WebApplication

Potok przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań, wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Przebieg 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. Ta sytuacja nie obejmuje rzeczywistego potoku przetwarzania żą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 reprezentuje następnego delegata w potoku. Można przerwać działanie potoku, nie wywołując 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 przerywaniem potoku żądania. Krótkie zwarcie jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie 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. Niemniej jednak, zapoznaj się z następującym ostrzeżeniem dotyczącym próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj elementu next.Invoke po tym, jak odpowiedź została wysłana 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 powoduje zgłoszenie wyjątku. Zapisywanie w treści odpowiedzi po wywołaniu komponentu 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 ciała. Na przykład zapisanie stopki HTML do pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub treść została zapisana.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i kończy 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.

Preferuj przeciążenie app.Use, które wymaga przekazania kontekstu do parametru 'next'

Metoda rozszerzenia nieprzydzielająca zasobów app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Eliminuje dwie wewnętrzne alokacje per-request, które są konieczne podczas korzystania z innego wariantu 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 uporządkowane są istniejące middleware oraz gdzie dodaje się niestandardowe middleware. 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 middlewarowe punktu końcowego na wcześniejszym diagramie wykonuje przepływ filtracyjny dla odpowiedniego typu aplikacji — MVC lub Razor Strony.

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 app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku procesu. 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();

W poprzednim kodzie:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
    • 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.
    • Element UseRequestLocalization musi pojawić się przed jakimkolwiek middleware, 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:
      • Strona wyjątków dla programistów (Middleware) (UseDeveloperExceptionPage) zgłasza błędy wykonania 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 obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w kolejnych pośrednikach.
      • Oprogramowanie pośredniczące protokołu HTTP Strict Transport Security (HSTS) (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 przerywa dalsze przetwarzanie żądania.
  4. Polityka Middleware (Cookie) (UseCookiePolicy) zapewnia zgodność aplikacji z rozporządzeniem o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące do routingu (UseRouting) do trasowania żą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 do routingu punktów końcowych (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych 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 też oprogramowanie pośredniczące obsługi wyjątków przechwytuje wszelkie wyjątki, które występują w późniejszych wywołaniach.

Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, aby mogło obsługiwać żądania i przerywać ich przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie przeprowadza 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 przerywa żądań nieuwierzytelnionych. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybierze określoną stronę Razor lub kontroler 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 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ść UseCors i UseStaticFiles

Kolejność modułu "Forwarded Headers Middleware"

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innymi oprogramowaniami pośredniczącymi. Ustalenie tej kolejności gwarantuje, że middleware opierające się na informacjach z przekazanych nagłówków może korzystać z 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 kanału oprogramowania pośredniego

Rozszerzenia Map są używane jako standard do rozgałęziania procesu. Element 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 Odpowiedź
localhost:1234 Witaj od delegata nie-Mapy.
localhost:1234/map1 Test mapy 1
localhost:1234/map2 Test mapy 2
localhost:1234/map3 Witaj od delegata nie-Mapy.

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.

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

MapWhen rozgałęzia potok żądania w oparciu o wynik 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 Odpowiedź
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. W przeciwieństwie do MapWhen, ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie przerywa działania 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ą parametru 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 zawiera uwagi na temat umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunki, w których może ono przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia innemu oprogramowaniu pośredniczącemu dalsze przetwarzanie żądania, nazywane jest 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
Uwierzytelnianie Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Terminal dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Cookie Polityka Ś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 wydaje pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
MECHANIZM 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 pierwszy komponent w potoku, gdy środowisko to Deweloperskie.
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. Terminal obsługujący wyjątki lub 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. Zakończ, jeśli żądanie pasuje do punktu końcowego kontroli stanu zdrowia.
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 łańcucha 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 do zwiększania 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ńcowy, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Terminalne, jeśli oprogramowanie pośredniczące OWIN przetwarza w pełni żą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 komponentami wrażliwymi 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ń. Terminal do dopasowywania tras.
UZDROWISKO Obsługuje wszystkie żądania od tego punktu w łańcuchu middleware, zwracając domyślną stronę dla Single Page Application (SPA). Na końcu łańcucha, aby inne oprogramowanie pośredniczące, które obsługuje pliki statyczne, akcje MVC itp., miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji użytkownika.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Zakończ, jeśli żądanie pasuje do pliku.
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 łańcucha oprogramowania pośredniczącego.
WebSockety 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ć dalej żądanie do następnego składnika w potoku.
  • Może wykonywać pracę przed i po następnym elemencie w przepływie pracy.

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 anonimowe funkcje w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy komponent pośredniczący w potoku żądania jest odpowiedzialny za wywoływanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu żądania przez oprogramowanie pośredniczące.

Migrowanie modułów HTTP do oprogramowania pośredniczącego ASP.NET Core wyjaśnia różnicę między potokami żądań w 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 przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań, wywoływanych jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Przebieg 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. Ta sytuacja nie obejmuje rzeczywistego potoku przetwarzania żą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 reprezentuje następnego delegata w potoku. Można przerwać przepływ danych, nie wywołując parametru 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 przerywaniem potoku żądania. Krótkie zwarcie jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład statyczne oprogramowanie pośredniczące plików może działać jako oprogramowanie pośredniczące terminalu, przetwarzając żądanie dotyczące pliku statycznego i zwarcie 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. Niemniej jednak, zapoznaj się z następującym ostrzeżeniem dotyczącym próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj elementu next.Invoke po tym, jak odpowiedź została wysłana 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 powoduje zgłoszenie wyjątku. Zapisywanie w treści odpowiedzi po wywołaniu komponentu 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 ciała. Na przykład zapisanie stopki HTML do pliku CSS.

HasStarted to przydatna wskazówka informująca, czy nagłówki zostały wysłane lub treść została zapisana.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i kończy 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 uporządkowane są istniejące middleware oraz gdzie dodaje się niestandardowe middleware. 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 middlewarowe punktu końcowego na wcześniejszym diagramie wykonuje przepływ filtracyjny dla odpowiedniego typu aplikacji — MVC lub Razor Strony.

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

W poprzednim kodzie:

  • Oprogramowanie pośredniczące, które nie jest dodawane podczas tworzenia nowej aplikacji internetowej z kontami poszczególnych użytkowników, jest zakomentowane.
  • Nie każde oprogramowanie pośredniczące pojawia się w tej dokładnej kolejności, ale wiele tak. Na przykład:
    • 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.
    • Element UseRequestLocalization musi pojawić się przed jakimkolwiek middleware, 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:
      • Strona wyjątków dla programistów (Middleware) (UseDeveloperExceptionPage) zgłasza błędy wykonania 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 obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w kolejnych pośrednikach.
      • Oprogramowanie pośredniczące protokołu HTTP Strict Transport Security (HSTS) (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 przerywa dalsze przetwarzanie żądania.
  4. Polityka Middleware (Cookie) (UseCookiePolicy) zapewnia zgodność aplikacji z rozporządzeniem o ochronie danych (RODO) w UE.
  5. Oprogramowanie pośredniczące do routingu (UseRouting) do trasowania żą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 do routingu punktów końcowych (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych 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 też oprogramowanie pośredniczące obsługi wyjątków przechwytuje wszelkie wyjątki, które występują w późniejszych wywołaniach.

Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, aby mogło obsługiwać żądania i przerywać ich przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie przeprowadza 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 przerywa żądań nieuwierzytelnionych. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybierze określoną stronę Razor lub kontroler 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 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 pojawia się na końcu.

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

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

Kolejność modułu "Forwarded Headers Middleware"

Oprogramowanie pośredniczące przekazanych nagłówków powinno być uruchamiane przed innymi oprogramowaniami pośredniczącymi. Ustalenie tej kolejności gwarantuje, że middleware opierające się na informacjach z przekazanych nagłówków może korzystać z 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 kanału oprogramowania pośredniego

Rozszerzenia Map są używane jako standard do rozgałęziania procesu. Element 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 Odpowiedź
localhost:1234 Witaj od delegata nie-Mapy.
localhost:1234/map1 Test mapy 1
localhost:1234/map2 Test mapy 2
localhost:1234/map3 Witaj od delegata nie-Mapy.

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.

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

MapWhen rozgałęzia potok żądania w oparciu o wynik 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 Odpowiedź
localhost:1234 Witaj od delegata nie-Mapy.
localhost:1234/?branch=main Używana gałąź = main

Instrukcja UseWhen rozgałęzia także potok żądania na podstawie wyniku danego predykatu. W przeciwieństwie do MapWhen, ta gałąź jest ponownie dołączana do głównego potoku, jeśli nie przerywa działania 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ą parametru 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 zawiera uwagi na temat umieszczania oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunki, w których może ono przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia innemu oprogramowaniu pośredniczącemu dalsze przetwarzanie żądania, nazywane jest 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
Antyfałszerstwo Zapewnia obsługę ochrony przed fałszowaniem żądań. Po uwierzytelnieniu i autoryzacji przed punktami końcowymi.
Uwierzytelnianie Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Terminal dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Bezpośrednio po oprogramowaniu pośredniczącym uwierzytelniania.
Cookie Polityka Ś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 wydaje pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
MECHANIZM 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. Terminal obsługujący wyjątki lub 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. Zakończ, jeśli żądanie pasuje do punktu końcowego kontroli stanu zdrowia.
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 do zwiększania 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ńcowy, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Terminalne, jeśli oprogramowanie pośredniczące OWIN przetwarza w pełni żą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 komponentami wrażliwymi 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ń. Terminal do dopasowywania tras.
UZDROWISKO Obsługuje wszystkie żądania od tego punktu w łańcuchu middleware, zwracając domyślną stronę dla Single Page Application (SPA). Na końcu łańcucha, aby inne oprogramowanie pośredniczące, które obsługuje pliki statyczne, akcje MVC itp., miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji użytkownika.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Zakończ, jeśli żądanie pasuje do pliku.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
WebSockety Włącza protokół WebSocket. Przed składnikami wymaganymi do akceptowania żądań protokołu WebSocket.

Dodatkowe zasoby