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.
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.
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.
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
iUseAuthorization
muszą pojawić się w pokazanej kolejności. - Obecnie składnik
UseCors
musi się pojawić przed składnikiemUseResponseCaching
. 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ładapp.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 poUseRouting
. Podczas wywoływania tylko globalnych ograniczników,UseRateLimiter
można wywołać przedUseRouting
.
-
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:
- 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
.
- Gdy aplikacja jest uruchamiana w środowisku programistycznym:
- Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
- Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i przerywa dalsze przetwarzanie żądania.
- Polityka Middleware (Cookie) (UseCookiePolicy) zapewnia zgodność aplikacji z rozporządzeniem o ochronie danych (RODO) w UE.
- Oprogramowanie pośredniczące do routingu (UseRouting) do trasowania żądań.
- Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
- Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
- 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.
- 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 , UseDeveloperExceptionPage i 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
- Opcje okresu istnienia i rejestracji zawierają kompletną próbkę middleware z usługami o okresie istnienia zasięgu, przejściowym i singleton.
- Tworzenie niestandardowego oprogramowania pośredniczącego w ASP.NET Core
- Test oprogramowania pośredniczącego ASP.NET Core
- Konfigurowanie usługi gRPC-Web na platformie ASP.NET Core
- Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core
- Uruchamianie aplikacji na platformie ASP.NET Core
- Żądanie funkcji na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego opartego na fabryce na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego przy użyciu kontenera innej firmy na platformie ASP.NET Core
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.
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.
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.
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
iUseAuthorization
muszą pojawić się w pokazanej kolejności. - Obecnie składnik
UseCors
musi się pojawić przed składnikiemUseResponseCaching
. 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ładapp.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 poUseRouting
. Podczas wywoływania tylko ograniczników globalnychUseRateLimiter
można wywołać przedUseRouting
.
-
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:
- 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
.
- Gdy aplikacja jest uruchamiana w środowisku programistycznym:
- Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
- Oprogramowanie pośredniczące do obsługi plików statycznych (UseStaticFiles) zwraca pliki statyczne i przerywa dalsze przetwarzanie żądania.
- Oprogramowanie pośredniczące Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z unijnym ogólnym rozporządzeniem o ochronie danych (RODO).
- Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
- Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
- Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
- 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.
- 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
- Opcje okresu istnienia i rejestracji zawierają kompletny przykład middleware z usługami o okresie istnienia: zakresowy, przejściowy i singleton.
- Tworzenie niestandardowego oprogramowania pośredniczącego dla ASP.NET Core
- Testowanie middleware ASP.NET Core
- Konfigurowanie usługi gRPC-Web na platformie ASP.NET Core
- Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core
- Uruchamianie aplikacji na platformie ASP.NET Core
- Żądanie funkcji na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego opartego na fabryce na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego przy użyciu kontenera innej firmy na platformie ASP.NET Core
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.
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.
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.
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
iUseAuthorization
muszą pojawić się w podanej kolejności. - Obecnie składnik
UseCors
musi się pojawić przed składnikiemUseResponseCaching
. 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ładapp.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:
- 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
.
- Gdy aplikacja jest uruchamiana w środowisku programistycznym:
- Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
- Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i pomija dalsze przetwarzanie żądania.
- Oprogramowanie pośredniczące Cookie (UseCookiePolicy) zapewnia zgodność aplikacji z ogólnym rozporządzeniem o ochronie danych (RODO) UE.
- Oprogramowanie pośredniczące (UseRouting) do trasowania żądań.
- Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
- Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
- 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.
- 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
- Opcje cyklu życia i rejestracji zawierają kompletny przykład oprogramowania pośredniczącego z usługami o cyklu życia o określonym zakresie, przejściowym i singleton.
- Tworzenie niestandardowego oprogramowania pośredniczącego ASP.NET Core
- Testowanie pośredniczącego oprogramowania ASP.NET Core
- Konfigurowanie usługi gRPC-Web na platformie ASP.NET Core
- Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core
- Uruchamianie aplikacji na platformie ASP.NET Core
- Żądanie funkcji na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego opartego na fabryce na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego przy użyciu kontenera innej firmy na platformie ASP.NET Core
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.
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.
Oprogramowanie pośredniczące punktu końcowego na powyższym diagramie wykonuje potok filtru dla odpowiedniego typu aplikacji — MVC lub Razor Pages.
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
iUseAuthorization
powinny pojawić się w pokazanej kolejności. - Obecnie składnik
UseCors
musi pojawiać się przed składnikiemUseResponseCaching
z powodu tej usterki. - Metoda
UseRequestLocalization
musi pojawić się przed jakimkolwiek oprogramowaniem pośredniczącym, które może sprawdzić kulturę żądania (na przykładapp.UseMvcWithDefaultRoute()
).
- Elementy
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:
- 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
.
- Gdy aplikacja jest uruchamiana w środowisku programistycznym:
- Oprogramowanie pośredniczące przekierowania HTTPS (UseHttpsRedirection) przekierowuje żądania HTTP do protokołu HTTPS.
- Oprogramowanie pośredniczące plików statycznych (UseStaticFiles) zwraca pliki statyczne i omija dalsze przetwarzanie żądania.
- Oprogramowanie pośredniczące Cookie (UseCookiePolicy) dostosowuje aplikację do przepisów ogólnego rozporządzenia o ochronie danych osobowych (RODO) w UE.
- Oprogramowanie pośredniczące routingu (UseRouting) do kierowania żądań.
- Oprogramowanie pośredniczące uwierzytelniania (UseAuthentication) próbuje uwierzytelnić użytkownika przed zezwoleniem mu na uzyskiwanie dostępu do bezpiecznych zasobów.
- Oprogramowanie pośredniczące autoryzacji (UseAuthorization) autoryzuje użytkownika do uzyskiwania dostępu do bezpiecznych zasobów.
- 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.
- 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
- Opcje okresu życia i rejestracji zawierają kompletny przykład oprogramowania pośredniczącego z usługami o okresie życia scoped, transient i singleton.
- Tworzenie niestandardowego middleware dla ASP.NET Core
- Testowanie oprogramowania pośredniczącego platformy ASP.NET Core
- Migrowanie modułów i programów obsługi HTTP do oprogramowania pośredniczącego platformy ASP.NET Core
- Uruchamianie aplikacji na platformie ASP.NET Core
- Żądanie funkcji na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego opartego na fabryce na platformie ASP.NET Core
- Aktywacja oprogramowania pośredniczącego przy użyciu kontenera innej firmy na platformie ASP.NET Core