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 dla platformy .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 dla .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 i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core wyjaśnia różnicę między potokami żądań na platformach ASP.NET Core i ASP.NET 4.x oraz udostępnia dodatkowe przykłady oprogramowania pośredniczącego.

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 spoza 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
Authentication 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).
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.
SPA 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 potoku 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:

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

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

Delegaci żądań są konfigurowani przy użyciu metod rozszerzeń Run, Map i Use. Pojedynczego delegata żądania można określić wewnątrz kodu jako metodę anonimową (nazywaną środkiem wewnątrz kodu) lub zdefiniować w klasie wielokrotnego użytku. Te klasy wielokrotnego użytku i metody anonimowe w linii to oprogramowanie pośredniczące, nazywane również składnikami oprogramowania pośredniczącego. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywołanie następnego składnika w potoku lub przerwanie potoku. Gdy oprogramowanie pośredniczące przerywa działanie, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega dalszemu przetwarzaniu przez oprogramowanie pośredniczące.

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

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 przepływ middleware za pomocą elementu WebApplication

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

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

Każdy delegat może wykonywać operacje przed następnym delegatem i po nim. Delegaty obsługujące wyjątki powinny być wywoływane na wczesnym etapie w kolejce, aby mogły przechwytywać wyjątki występujące w późniejszych etapach kolejki.

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten przypadek nie obejmuje rzeczywistego procesu 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 linii przetwarzania. Można pominąć proces, gdy nie wywoła się parametr next. Zazwyczaj można wykonywać akcje zarówno przed delegatem next, jak i po nim, jak pokazano w poniższym przykładzie:

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

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

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

app.Run();

Gdy delegat nie przekazuje żądania do następnego delegata, jest to nazywane tworzeniem skrótu w potoku żądania. Tworzenie skrótu jest często pożądane, ponieważ pozwala uniknąć niepotrzebnej pracy. Na przykład 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. Zobacz jednak następujące ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

Nie wywołuj 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 składnika next:

  • Może spowodować naruszenie protokołu. Na przykład zapisanie dłuższej treści niż określona wartość Content-Length.
  • Może uszkodzić format 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 czy treść została zapisana.

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowy i zamyka 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 metody app.Use, które wymaga przekazania kontekstu do następnego składnika.

Nieprzydzielająca metoda rozszerzenia funkcji app.Use:

  • Wymaga przekazania kontekstu do składnika next.
  • Oszczędza dwie wewnętrzne alokacje przy każdym żądaniu, które są wymagane podczas używania 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 jest istniejące oprogramowanie pośredniczące i gdzie dodaje się niestandardowe oprogramowanie pośredniczące. Masz pełną kontrolę nad tym, jak zmienić kolejność istniejących oprogramowań pośredniczących lub wstrzyknąć nowe niestandardowe oprogramowania pośredniczące odpowiednio do potrzeb w scenariuszach.

Potok pośredniczący ASP.NET Core

Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtrów dla danego rodzaju aplikacji — MVC lub Razor Pages.

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

Potok filtru platformy ASP.NET Core

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

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

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

var builder = WebApplication.CreateBuilder(args);

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

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

var app = builder.Build();

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

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

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

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

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

app.Run();

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, gdy używane są interfejsy API specyficzne dla punktu końcowego ograniczające szybkość. Na przykład, jeśli używany jest atrybut [EnableRateLimiting], UseRateLimiter musi być wywołany po UseRouting. Podczas wywoływania tylko ograniczników globalnych 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 programisty w middleware (UseDeveloperExceptionPage) zgłasza błędy w czasie działania 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 do obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w kolejnych warstwach oprogramowania pośredniczącego.
      • Oprogramowanie pośredniczące protokołu HSTS (HTTP Strict Transport Security) (UseHsts) dodaje nagłówek Strict-Transport-Security.
  2. Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
  3. Oprogramowanie pośredniczące do obsługi plików statycznych (UseStaticFiles) zwraca pliki statyczne i przerywa dalsze przetwarzanie żądania.
  4. Oprogramowanie pośredniczące Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z unijnym ogólnym rozporządzeniem o ochronie danych (RODO).
  5. Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
  6. Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
  7. Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
  8. Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po Policy Middleware Cookie i przed oprogramowaniem pośredniczącym MVC.
  9. Oprogramowanie pośredniczące do routingu końcowego (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 komponent pośredniczący dodany do pipeline'u. Dlatego oprogramowanie pośredniczące programu obsługi wyjątków przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.

Oprogramowanie pośredniczące do obsługi plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i zakończyć przetwarzanie bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie wykonuje żadnych 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 pomija nieuwierzytelnionych żądań. Chociaż middleware uwierzytelniające uwierzytelnia żądania, autoryzacja (i odrzucenie) odbywa się 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ść elementó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ść obsługi przekazywanych nagłówków przez oprogramowanie pośredniczące

Oprogramowanie middleware przesyłanych nagłówków powinno być uruchamiane przed innym middleware. Takie określenie kolejności gwarantuje, że oprogramowanie pośredniczące, które opiera się na informacjach z przekazywanych nagłówków, może wykorzystywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.

Rozgałęzianie potoku oprogramowania pośredniczącego

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

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

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

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

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

app.Run();

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

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

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

Zażądaj Odpowiedź
localhost:1234 Witam od delegata niebędącego częścią Map.
localhost:1234/map1 Map Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Cześć od delegata niebędącego częścią Map.

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.

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

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

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

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

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

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

app.Run();

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

Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do skierowania żą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ą ciągu zapytania branch, jego wartość jest rejestrowana przed ponownym włączeniem do głównego przepływu.

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 żądań oraz warunki, w których może ono zakończyć przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia dalsze przetwarzanie żądania przez inne oprogramowanie pośredniczące, 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
Authentication 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).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
DeveloperExceptionPage Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym. Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze w potoku, gdy środowisko jest ustawione na 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 serwujący domyślną stronę internetową dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed elementami korzystającymi z zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Rejestrowanie HTTP Rejestruje żądania i odpowiedzi HTTP. Na początku potoku oprogramowania pośredniczącego.
Zastępowanie metody HTTP Pozwala przychodzącemu żądaniu POST zastąpić metodę. 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 wzmacniające zabezpieczenia, 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 pasuje do trasy.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Jeśli oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie, jest ono końcowe.
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 wsparcie dla buforowania odpowiedzi. Wymaga to udziału klienta w pracy. Użyj buforowania danych wyjściowych do pełnej kontroli serwera. Przed składnikami wymagającymi buforowania. Składnik UseCORS musi znajdować się przed składnikiem UseResponseCaching. Zazwyczaj nie jest korzystne dla aplikacji interfejsu użytkownika, takich jak Razor Strony, ponieważ przeglądarki zwykle ustawiają nagłówki żądań, które uniemożliwiają buforowanie. Buforowanie danych wyjściowych zapewnia korzyści dla aplikacji interfejsu użytkownika.
Dekompresja żądań Zapewnia obsługę dekompresowania żądań. Przed składnikami odczytującymi treść żądania.
Kompresja odpowiedzi Zapewnia obsługę kompresowania odpowiedzi. Przed składnikami, które wymagają kompresji.
Lokalizacja żądania Zapewnia obsługę lokalizacji. Przed składnikami czułymi na lokalizację. W przypadku korzystania ze składnika RouteDataRequestCultureProvider musi pojawiać się po oprogramowaniu pośredniczącym routingu.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Terminal do dopasowywania tras.
SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają Sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowe, jeśli żądanie jest zgodne z plikiem.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
Rejestrowanie W3C Generuje dzienniki dostępu serwera w formacie rozszerzonego pliku dziennika W3C. Na początku potoku oprogramowania pośredniczącego.
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 należy przekazać żą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ć bezpośrednio w kodzie jako metodę anonimową (nazywaną middleware in-line) lub można go zdefiniować w klasie wielokrotnego użytku. Te klasy do ponownego użycia i osadzone w kodzie metody anonimowe to middleware, nazywane również składnikami middleware. Każdy komponent oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywołanie następnego komponentu w potoku lub przerwanie działania potoku. Gdy oprogramowanie pośredniczące przerywa działanie, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.

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

Analiza kodu oprogramowania pośredniczącego

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

Utwórz potok oprogramowania pośredniczącego z WebApplication

Potok przetwarzania żądań w ASP.NET Core składa się z sekwencji delegatów żądań wywoływanych kolejno. Na poniższym diagramie przedstawiono tę koncepcję. Wykonywanie wątku 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. Delegaty obsługujące wyjątki powinny być wywoływane na wczesnym etapie ciągu procesów, aby mogły przechwytywać wyjątki występujące w późniejszych etapach tego ciągu.

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. W tym przypadku nie obejmuje rzeczywistego kanału przetwarzania żądań. 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 skrócić działanie potoku, gdy nie wywołuje się 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 żądań. Tworzenie skrótu 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. Jednak zwróć uwagę na poniższe ostrzeżenie dotyczące próby zapisania w odpowiedzi, która została już wysłana.

Ostrzeżenie

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

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

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

Delegaci Run nie otrzymują parametru next. Pierwszy delegat Run jest zawsze końcowym delegatem i zakończa 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 metody app.Use, które wymaga przekazania kontekstu do następnego składnika.

Metoda rozszerzenia app.Use bez alokacji pamięci:

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

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

Kolejność oprogramowania pośredniczącego

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

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

Oprogramowanie pośredniczące Endpoint na powyższym diagramie wykonuje potok filtru 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 funkcji app.UseRouting, oprogramowanie pośredniczące Routing będzie domyślnie uruchamiane na początku potoku. Aby uzyskać więcej informacji, zobacz Routing.

Potok filtru platformy ASP.NET Core

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

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

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

var builder = WebApplication.CreateBuilder(args);

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

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

var app = builder.Build();

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

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

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

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

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

app.Run();

W poprzednim fragmencie kodu:

  • 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 podanej 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:
      • Oprogramowanie pośredniczące strony wyjątku dla deweloperów (UseDeveloperExceptionPage) zgłasza błędy środowiska uruchomieniowego aplikacji.
      • Oprogramowanie pośredniczące strony błędu bazy danych (UseDatabaseErrorPage) zgłasza błędy środowiska uruchomieniowego bazy danych.
    • Gdy aplikacja działa w środowisku produkcyjnym:
      • Oprogramowanie pośredniczące obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w następującym oprogramowaniu pośredniczącym.
      • Oprogramowanie pośredniczące protokołu HSTS (HTTP Strict Transport Security) (UseHsts) dodaje nagłówek Strict-Transport-Security.
  2. Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
  3. Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i pomija dalsze przetwarzanie żądania.
  4. Oprogramowanie pośredniczące Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z ogólnym rozporządzeniem o ochronie danych (RODO) UE.
  5. Oprogramowanie pośredniczące (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. Pośredniczące oprogramowanie routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych stron Razor 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 Middleware obsługujący wyjątki przechwytuje wszelkie wyjątki występujące w dalszych wywołaniach.

Oprogramowanie middleware do obsługi plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i pominąć 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 pomija nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) występuje dopiero po tym, jak MVC wybiera konkretną 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. Można skompresować odpowiedzi Pages.

// 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ść użycia UseCors i UseStaticFiles

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

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

Rozgałęzianie potoku oprogramowania pośredniczącego

Rozszerzenia Map są używane jako standard do rozgałęziania przepływu. Element Map rozgałęzia przepływ żą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 niezwiązanego z Mapą.
localhost:1234/map1 Mapa Test 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Witam od delegata spoza 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.

Map obsługuje zagnieżdżanie, na przykładzie:

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

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

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

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

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

app.Run();

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

Instrukcja MapWhen rozgałęzia potok żądania na podstawie wyniku danego predykatu. Dowolny predykat typu Func<HttpContext, bool> może zostać użyty do mapowania żądań na nową gałąź przepływu. 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 odróżnieniu od MapWhen, ta gałąź jest ponownie dołączana do głównej ścieżki, jeśli nie dochodzi do krótkiego spięcia lub nie zawiera terminalnego middleware:

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

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

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

app.Run();

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

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

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

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

Wbudowane oprogramowanie pośredniczące

Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order zawiera informacje dotyczące rozmieszczenia oprogramowania pośredniczącego w potoku przetwarzania żądania oraz warunków, w których oprogramowanie pośredniczące może przerwać przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa potok przetwarzania żądania i uniemożliwia dalszym komponentom pośredniczącym przetwarzanie żądania, jest nazywane końcowym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat zwarć, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego za pomocą aplikacji internetowej .

Oprogramowanie pośredniczące opis Zamówienie
Authentication Zapewnia obsługę uwierzytelniania. Przedtem jest wymagany składnik HttpContext.User. Punkt 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 wystawia pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
DeveloperExceptionPage Generuje stronę z informacjami o błędzie przeznaczonymi do użytku tylko w środowisku programistycznym. Przed składnikami, które generują błędy. Szablony projektów automatycznie rejestrują to oprogramowanie pośredniczące jako pierwsze w potoku, gdy środowisko to Rozwój.
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 dla wyjątków lub obsługi domyślnej strony internetowej dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed składnikami korzystającymi ze zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Rejestrowanie HTTP Rejestruje żądania i odpowiedzi HTTP. Na początku potoku oprogramowania pośredniczącego.
Zastępowanie metody HTTP Zezwala na zastąpienie metody przez przychodzące żądanie POST. 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 bezpieczeństwa, które dodaje specjalny nagłówek odpowiedzi. Przed wysłaniem odpowiedzi i po składnikach modyfikujących żądania. Przykłady: przekazane nagłówki, ponowne zapisywanie adresu URL.
MVC Przetwarza żądania za pomocą produktu MVC/Razor Pages. Końcowe, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Końcowy, gdy oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie.
Dekompresja żądań Zapewnia obsługę dekompresowania żądań. Zanim składniki odczytają treść żądania.
Buforowanie odpowiedzi Zapewnia obsługę keszowania 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ę. Korzystając ze składnika RouteDataRequestCultureProvider, należy umieścić go za oprogramowaniem pośredniczącym routingu.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Terminal dla pasujących tras.
Aplikacja SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowy, 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.
WebSockets Włącza protokoły WebSocket. Przed składnikami wymaganymi do obsługi żądań WebSocket.

Dodatkowe zasoby

Autorzy: Rick Anderson i Steve Smith

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

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

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. Delegata dla pojedynczego żądania można określić w linii jako metodę anonimową (nazywaną w linii oprogramowaniem pośredniczącym) lub zdefiniować w odrębnej klasie. Te klasy wielokrotnego użytku i wbudowane metody anonimowe to middleware, nazywane również składnikami middleware. Każdy składnik oprogramowania pośredniczącego w potoku żądania jest odpowiedzialny za wywoływanie następnego składnika w potoku lub tworzenie skrótu w potoku. Gdy oprogramowanie pośredniczące zatrzymuje się, jest ono nazywane końcowym oprogramowaniem pośredniczącym, ponieważ zapobiega przetwarzaniu żądania przez dalsze oprogramowanie pośredniczące.

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

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

Potok przetwarzania żądań platformy ASP.NET Core składa się z sekwencji delegatów, które są wywoływane jeden po drugim. Na poniższym diagramie przedstawiono tę koncepcję. Wykonywanie wątku przebiega zgodnie z czarnymi strzałkami.

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

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

Najprostsza możliwa aplikacja platformy ASP.NET Core konfiguruje jednego delegata żądania, który obsługuje wszystkie żądania. Ten scenariusz nie obejmuje rzeczywistego przepływu żą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 kolejnego 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 tworzeniem skrótu w potoku żądania. Krótkie spięcie 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. Należy mieć na uwadze następujące ostrzeżenie dotyczące próby zapisania odpowiedzi, która została już wysłana.

Ostrzeżenie

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

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

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

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

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 przepływ danych. 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 uporządkowane są istniejące middleware w typowej aplikacji i gdzie są dodawane 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 pośredniczący ASP.NET Core

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

Potok filtru platformy ASP.NET Core

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

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

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

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

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

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

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

Poprzedni kod:

  • Oprogramowanie pośredniczące, które nie zostaje dodane podczas tworzenia nowej aplikacji internetowej z kontami indywidualnych 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:
    • Elementy UseCors, UseAuthentication i UseAuthorization powinny pojawić się w pokazanej kolejności.
    • Obecnie składnik UseCors musi pojawiać się przed składnikiem UseResponseCaching z powodu tej usterki.
    • Metoda UseRequestLocalization musi pojawić się przed jakimkolwiek oprogramowaniem pośredniczącym, które może sprawdzić kulturę żądania (na przykład app.UseMvcWithDefaultRoute()).

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

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

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

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

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

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

  1. Obsługa wyjątków/błędów
    • Gdy aplikacja jest uruchamiana w środowisku programistycznym:
      • Oprogramowanie pośredniczące dla strony wyjątków dewelopera (UseDeveloperExceptionPage) zgłasza błędy środowiska uruchomieniowego aplikacji.
      • Oprogramowanie pośredniczące strony błędu bazy danych zgłasza błędy środowiska uruchomieniowego bazy danych.
    • Gdy aplikacja działa w środowisku produkcyjnym:
      • Oprogramowanie pośredniczące programu obsługi wyjątków (UseExceptionHandler) przechwytuje wyjątki zgłoszone w następujących oprogramowaniach pośredniczących.
      • Oprogramowanie pośredniczące protokołu 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 omija dalsze przetwarzanie żądania.
  4. Oprogramowanie pośredniczące Cookie (UseCookiePolicy) dostosowuje aplikację do przepisów ogólnego rozporządzenia o ochronie danych osobowych (RODO) w UE.
  5. Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
  6. Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
  7. Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
  8. Oprogramowanie pośredniczące sesji (UseSession) ustanawia i utrzymuje stan sesji. Jeśli aplikacja używa stanu sesji, wywołaj oprogramowanie pośredniczące sesji po oprogramowaniu pośredniczącym dotyczącym zasad Cookie i przed oprogramowaniem pośredniczącym MVC.
  9. Oprogramowanie pośredniczące routingu punktu końcowego (UseEndpoints z MapRazorPages) służące do dodawania punktów końcowych stron Razor 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 komponent oprogramowania pośredniczącego dodany do potoku. Dlatego middleware obsługujący wyjątki przechwytuje wszelkie wyjątki występujące w kolejnych wywołaniach.

Oprogramowanie pośredniczące plików statycznych jest wywoływane na początku potoku, dzięki czemu może obsługiwać żądania i tworzyć skrót bez przechodzenia przez pozostałe składniki. Oprogramowanie pośredniczące plików statycznych nie wykonuje 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 omija ani nie przerywa obsługi nieuwierzytelnionych żądań. Mimo że oprogramowanie pośredniczące uwierzytelniania uwierzytelnia żądania, autoryzacja (i odrzucenie) następuje dopiero po wybraniu przez MVC określonej strony Razor lub kontrolera i akcji MVC.

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ść przekazywanych nagłówków w oprogramowaniu pośredniczącym

Oprogramowanie pośredniczące dla przekazanych nagłówków powinno działać przed innymi komponentami pośredniczącymi. Takie ustawienie kolejności gwarantuje, że oprogramowanie pośredniczące korzystające z informacji z przekazanych nagłówków może wykorzystywać wartości nagłówków do przetwarzania. Aby uruchomić oprogramowanie pośredniczące przekazanych nagłówków po oprogramowaniu pośredniczącym diagnostyki i obsługi błędów, zobacz Kolejność oprogramowania pośredniczącego przekazanych nagłówków.

Rozgałęzianie potoku oprogramowania pośredniczącego

Rozszerzenia Map są używane jako konwencja do rozgałęziania potoku. Komponent Map rozgałęzia potok żądań na podstawie dopasowania 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 Witam od delegata spoza mapy.
localhost:1234/map1 Test mapy 1
localhost:1234/map2 Map Test 2
localhost:1234/map3 Witaj od delegata spoza 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.

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

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

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

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

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

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

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

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

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

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

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

Zażądaj Odpowiedź
localhost:1234 Witaj od delegata niepowiązanego z Mapą.
localhost:1234/?branch=main Używana gałąź = main

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

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

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

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

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

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

Wbudowane oprogramowanie pośredniczące

Platforma ASP.NET Core jest dostarczana z następującymi składnikami oprogramowania pośredniczącego. Kolumna Order (Kolejność) zawiera uwagi dotyczące umieszczania pośrednictwa w potoku przetwarzania żądań oraz warunki, w jakich pośrednictwo może zakończyć przetwarzanie żądania. Gdy oprogramowanie pośredniczące przerywa proces przetwarzania żądania i uniemożliwia kolejnym warstwom oprogramowania pośredniczącego przetwarzanie żądania, jest nazywane terminalnym oprogramowaniem pośredniczącym. Aby uzyskać więcej informacji na temat tworzenia skrótów, zobacz sekcję Tworzenie potoku oprogramowania pośredniczącego przy użyciu programu IApplicationBuilder.

Oprogramowanie pośredniczące opis Zamówienie
Authentication Zapewnia obsługę uwierzytelniania. Zanim HttpContext.User będzie potrzebny. Terminal dla wywołań zwrotnych OAuth.
Autoryzacja Zapewnia obsługę autoryzacji. Zaraz po oprogramowaniu pośredniczącym do uwierzytelniania.
PolitykaCookie Śledzi zgodę użytkowników na przechowywanie danych osobowych i wymusza minimalne standardy dla pól cookie, takie jak secure i SameSite. Przed oprogramowaniem pośredniczącym, które wystawia pliki cookie. Przykłady: uwierzytelnianie, sesja, MVC (TempData).
CORS Konfiguruje współużytkowanie zasobów między źródłami. Przed składnikami korzystającymi z mechanizmu CORS. Obecnie składnik UseCors musi znajdować się przed składnikiem UseResponseCaching z powodu tej usterki.
Diagnostyka Kilka oddzielnych oprogramowań pośredniczących, które udostępniają stronę wyjątków dla deweloperów, obsługę wyjątków, strony kodu stanu i domyślną stronę internetową dla nowych aplikacji. Przed składnikami, które generują błędy. Terminal do wyjątków lub do obsługi domyślnej strony internetowej dla nowych aplikacji.
Przekazane nagłówki Przekazuje nagłówki przesłane przez serwer proxy do bieżącego żądania. Przed składnikami korzystającymi ze zaktualizowanych pól. Przykłady: schemat, host, adres IP klienta, metoda.
Kontrola kondycji Sprawdza kondycję aplikacji platformy ASP.NET Core i jej zależności, takie jak sprawdzanie dostępności bazy danych. Końcowe, jeśli żądanie jest zgodne z punktem końcowym kontroli kondycji.
Propagacja nagłówka Propaguje nagłówki HTTP z żądania przychodzącego do wychodzących żądań klienta HTTP.
Nadpisywanie 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) Middleware zwiększające zabezpieczenia, które dodaje specjalny nagłówek odpowiedzi. Przed wysłaniem odpowiedzi i po składnikach modyfikujących żądania. Przykłady: przekazane nagłówki, ponowne zapisywanie adresu URL.
MVC Przetwarza żądania za pomocą produktu MVC/Razor Pages. Końcowe, jeśli żądanie jest zgodne z trasą.
OWIN Współdziałanie z aplikacjami, serwerami i oprogramowaniem pośredniczącym opartymi na OWIN. Terminalne, jeśli oprogramowanie pośredniczące OWIN w pełni przetwarza żądanie.
Buforowanie odpowiedzi Zapewnia wsparcie dla cache'owania 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ę. Korzystając ze składnika RouteDataRequestCultureProvider, musi pojawiać się po oprogramowaniu pośredniczącym do routingu.
Routing punktów końcowych Definiuje i ogranicza trasy żądań. Terminal dla pasujących tras.
Aplikacja SPA Obsługuje wszystkie żądania z tego punktu w łańcuchu oprogramowania pośredniczącego, zwracając domyślną stronę dla aplikacji jednostronicowej (SPA) Pod koniec łańcucha, tak aby inne oprogramowanie pośredniczące do obsługi plików statycznych, akcji MVC itp. miało pierwszeństwo.
Sesja Zapewnia obsługę zarządzania sesjami użytkowników. Przed składnikami, które wymagają Sesji.
Pliki statyczne Zapewnia obsługę plików statycznych i przeglądania katalogów. Końcowe, jeśli żądanie jest zgodne z plikiem.
Ponowne zapisywanie adresu URL Zapewnia obsługę ponownego zapisywania adresów URL i przekierowywania żądań. Przed składnikami korzystającymi z adresu URL.
WebSocket Włącza protokół WebSocket. Przed składnikami wymaganymi do akceptowania żądań protokołu WebSocket.

Dodatkowe zasoby