Ponowne zapisywanie oprogramowania pośredniczącego w adresie URL w programie ASP.NET Core
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu 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 platformy .NET 9.
Autor: Kirk Larkin i Rick Anderson
W tym artykule przedstawiono ponowne zapisywanie adresów URL z instrukcjami dotyczącymi używania oprogramowania pośredniczącego ponownego zapisywania adresów URL w aplikacjach ASP.NET Core.
Ponowne zapisywanie adresów URL to czynność modyfikowania adresów URL żądań na podstawie co najmniej jednej wstępnie zdefiniowanej reguły. Ponowne zapisywanie adresów URL powoduje utworzenie abstrakcji między lokalizacjami zasobów a ich adresami, dzięki czemu lokalizacje i adresy nie są ściśle połączone. Ponowne zapisywanie adresów URL jest przydatne w kilku scenariuszach:
- Tymczasowe lub trwałe przenoszenie lub zastępowanie zasobów serwera i utrzymywanie stabilnych lokalizatorów dla tych zasobów.
- Podziel przetwarzanie żądań między różne aplikacje lub obszary jednej aplikacji.
- Usuwanie, dodawanie lub reorganizacja segmentów adresów URL dla żądań przychodzących.
- Optymalizowanie publicznych adresów URL na potrzeby optymalizacji aparatu wyszukiwania (SEO).
- Zezwól na używanie przyjaznych publicznych adresów URL, aby ułatwić odwiedzającym przewidywanie zawartości zwracanej przez żądanie zasobu.
- Przekieruj niezabezpieczone żądania do bezpiecznych punktów końcowych.
- Zapobiegaj łączeniu gorąca, w którym witryna zewnętrzna używa hostowanego zasobu statycznego w innej witrynie, łącząc zasób z własną zawartością.
Ponowne zapisywanie adresów URL może zmniejszyć wydajność aplikacji. Ogranicz liczbę i złożoność reguł.
Przekierowanie adresu URL i ponowne zapisywanie adresów URL
Różnica w sformułowaniu między przekierowywaniem adresów URL a ponownym zapisywaniem adresów URL jest subtelna, ale ma ważne konsekwencje dla udostępniania zasobów klientom. ASP.NET Core adres URL ponownego zapisywania oprogramowania pośredniczącego jest w stanie sprostać potrzebom obu tych programów.
Przekierowanie adresu URL obejmuje operację po stronie klienta, gdzie klient jest poinstruowany, aby uzyskać dostęp do zasobu pod innym adresem niż klient pierwotnie zażądał. Wymaga to rundy na serwerze. Adres URL przekierowania zwrócony do klienta jest wyświetlany na pasku adresu przeglądarki, gdy klient wysyła nowe żądanie dla zasobu.
Jeśli /resource
nastąpi przekierowanie do /different-resource
usługi , serwer odpowiada, że klient powinien uzyskać zasób /different-resource
z kodem stanu wskazującym, że przekierowanie jest tymczasowe lub trwałe.
Podczas przekierowywania żądań do innego adresu URL wskaż, czy przekierowanie jest trwałe, czy tymczasowe, określając kod stanu z odpowiedzią:
Kod
301 - Moved Permanently
stanu jest używany, gdy zasób ma nowy, trwały adres URL i że wszystkie przyszłe żądania zasobu powinny używać nowego adresu URL. Klient może buforowania i ponownego użycia odpowiedzi po odebraniu kodu stanu 301.Kod
302 - Found
stanu jest używany, gdy przekierowanie jest tymczasowe lub zwykle może ulec zmianie. Kod stanu 302 wskazuje klientowi, aby nie przechowywał adresu URL i używał go w przyszłości.
Aby uzyskać więcej informacji na temat kodów stanu, zobacz RFC 9110: Definicje kodu stanu.
Ponowne zapisywanie adresu URL to operacja po stronie serwera, która udostępnia zasób z innego adresu zasobu niż żądany przez klienta. Ponowne zapisywanie adresu URL nie wymaga rundy na serwerze. Przepisany adres URL nie jest zwracany do klienta i nie jest wyświetlany na pasku adresu przeglądarki.
Jeśli /resource
element zostanie przepisany do /different-resource
elementu , serwer wewnętrznie pobiera i zwraca zasób pod adresem /different-resource
.
Mimo że klient może być w stanie pobrać zasób pod adresem URL przepisanego, klient nie jest informowany, że zasób istnieje pod adresem URL przepisanym, gdy wysyła żądanie i odbiera odpowiedź.
Ponowne zapisywanie adresów URL przykładowej aplikacji
Zapoznaj się z funkcjami adresu URL Ponowne zapisywanie oprogramowania pośredniczącego za pomocą przykładowej aplikacji. Aplikacja stosuje reguły przekierowania i ponownego zapisywania oraz wyświetla przekierowany lub przepisany adres URL w kilku scenariuszach.
Kiedy należy używać oprogramowania pośredniczącego ponownego zapisywania adresów URL
Użyj oprogramowania pośredniczącego ponownego zapisywania adresów URL, jeśli następujące podejścia nie są zadowalające:
- Moduł ponownego zapisywania adresów URL za pomocą usług IIS w systemie Windows Server
- Moduł Apache mod_rewrite na serwerze Apache
- Ponowne zapisywanie adresów URL w usłudze Nginx
Użyj adresu URL ponownego zapisywania oprogramowania pośredniczącego, gdy aplikacja jest hostowana na serwerze HTTP.sys.
Główne przyczyny używania technologii ponownego zapisywania adresów URL opartych na serwerze w usługach IIS, Apache i Nginx są następujące:
Oprogramowanie pośredniczące nie obsługuje pełnych funkcji tych modułów.
Niektóre funkcje modułów serwera nie działają z projektami ASP.NET Core, takimi jak
IsFile
iIsDirectory
ograniczenia modułu ponownego zapisywania usług IIS. W tych scenariuszach należy zamiast tego użyć oprogramowania pośredniczącego.Wydajność oprogramowania pośredniczącego prawdopodobnie nie jest zgodna z wydajnością modułów.
Benchmarking jest jedynym sposobem, aby wiedzieć z pewnością, który podejście obniża wydajność najbardziej lub jeśli obniżona wydajność jest nieznaczna.
Rozszerzenia i opcje
Ustanów reguły ponownego zapisywania adresów URL i przekierowywania, tworząc wystąpienie klasy RewriteOptions przy użyciu metod rozszerzeń dla każdej reguły ponownego zapisywania. Łączenie wielu reguł w kolejności ich przetwarzania. Element RewriteOptions
jest przekazywany do adresu URL Ponowne zapisywanie oprogramowania pośredniczącego, ponieważ jest on dodawany do potoku żądania za pomocą polecenia UseRewriter:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
W poprzednim kodzie MethodRules
jest klasą zdefiniowaną przez użytkownika. Więcej informacji można znaleźć RewriteRules.cs
w tym artykule.
Przekieruj nie-www na www
Trzy opcje umożliwiają aplikacji przekierowywanie żądań niezwiązanychwww
z żądaniami do www
:
AddRedirectToWwwPermanent: trwałe przekierowanie żądania do
www
poddomeny, jeśli żądanie nie jestwww
. Przekierowuje za pomocą kodu stanu Status308PermanentRedirect .AddRedirectToWww: przekieruj żądanie do
www
poddomeny, jeśli żądanie przychodzące nie jestwww
. Przekierowuje z kodem stanu Status307TemporaryRedirect . Przeciążenie zezwala na podanie kodu stanu odpowiedzi. Użyj pola StatusCodes klasy do przypisania kodu stanu.
Przekierowywanie adresów URL
Służy AddRedirect do przekierowywania żądań. Pierwszy parametr zawiera wyrażenie regularne platformy .NET (Regex) do dopasowywania w ścieżce przychodzącego adresu URL. Drugi parametr to ciąg zastępczy. Trzeci parametr, jeśli jest obecny, określa kod stanu. Jeśli kod stanu nie jest określony, kod stanu jest domyślnie ustawiony na 302 — Znaleziono, co oznacza, że zasób jest tymczasowo przenoszony lub zastępowany.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
W przeglądarce z włączonymi narzędziami deweloperskich prześlij żądanie do przykładowej aplikacji ze ścieżką /redirect-rule/1234/5678
. Wyrażenie regularne pasuje do ścieżki żądania w pliku redirect-rule/(.*)
, a ścieżka jest zastępowana ciągiem /redirected/1234/5678
. Adres URL przekierowania jest wysyłany z powrotem do klienta z kodem stanu 302 — Znaleziono . Przeglądarka wysyła nowe żądanie pod adresem URL przekierowania, które jest wyświetlane na pasku adresu przeglądarki. Ponieważ w adresie URL przekierowania nie są zgodne żadne reguły w przykładowej aplikacji:
- Drugie żądanie odbiera odpowiedź 200 — OK z aplikacji.
- Treść odpowiedzi zawiera adres URL przekierowania.
Podczas przekierowywania adresu URL następuje zaokrąglenie do serwera.
Ostrzeżenie
Podczas ustanawiania reguł przekierowania należy zachować ostrożność. Reguły przekierowania są oceniane dla każdego żądania do aplikacji, w tym po przekierowaniu. Łatwo jest przypadkowo utworzyć pętlę nieskończonych przekierowań.
Część wyrażenia zawartego w nawiasach jest nazywana grupą przechwytywania. Kropka (.
) wyrażenia oznacza dopasowanie dowolnego znaku. Gwiazdka (*
) wskazuje dopasowanie poprzedniego znaku zero lub więcej razy. W związku z tym ostatnie dwa segmenty ścieżki adresu URL są 1234/5678
przechwytywane przez grupę (.*)
przechwytywania . Dowolna wartość podana w adresie URL żądania po redirect-rule/
przechwyceniu przez tę pojedynczą grupę przechwytywania.
W ciągu zastępczym przechwycone grupy są wstrzykiwane do ciągu znakiem dolara ($
), a następnie numerem sekwencji przechwytywania. Pierwsza wartość grupy przechwytywania jest uzyskiwana za pomocą $1
elementu , drugiego z elementami $2
i są one kontynuowane w sekwencji dla grup przechwytywania w wyrażeniu regularnym. W wyrażeniu redirect-rule/(.*)
regularnym reguły przekierowania istnieje tylko jedna przechwycona grupa, więc w ciągu zastępczym znajduje się tylko jedna grupa, czyli $1
. Po zastosowaniu reguły adres URL zmieni się na /redirected/1234/5678
.
Spróbuj użyć /redirect-rule/1234/5678
narzędzi przeglądarki na karcie sieci.
Przekierowanie adresu URL do bezpiecznego punktu końcowego
Użyj polecenia AddRedirectToHttps , aby przekierować żądania HTTP do tego samego hosta i ścieżki przy użyciu protokołu HTTPS. Jeśli kod stanu nie zostanie podany, oprogramowanie pośredniczące domyślnie ma wartość 302 — Znaleziono. Jeśli port nie jest podany:
- Domyślnie oprogramowanie pośredniczące ma wartość
null
. - Schemat zmienia się na
https
(protokół HTTPS), a klient uzyskuje dostęp do zasobu na porcie 443.
W poniższym przykładzie pokazano, jak ustawić kod 301 - Moved Permanently
stanu na i zmienić port na port HTTPS używany przez Kestrel hosta lokalnego. W środowisku produkcyjnym port HTTPS ma wartość null:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
int? localhostHTTPSport = null;
if (app.Environment.IsDevelopment())
{
localhostHTTPSport = Int32.Parse(Environment.GetEnvironmentVariable(
"ASPNETCORE_URLS")!.Split(new Char[] { ':', ';' })[2]);
}
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
// localhostHTTPport not needed for production, used only with localhost.
.AddRedirectToHttps(301, localhostHTTPSport)
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Służy AddRedirectToHttpsPermanent do przekierowywania niezabezpieczonych żądań do tego samego hosta i ścieżki przy użyciu bezpiecznego protokołu HTTPS na porcie 443. Oprogramowanie pośredniczące ustawia kod stanu na 301 - Moved Permanently
.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Uwaga
Podczas przekierowywania do bezpiecznego punktu końcowego bez wymagania dodatkowych reguł przekierowania zalecamy użycie oprogramowania pośredniczącego przekierowania HTTPS. Aby uzyskać więcej informacji, zobacz Wymuszanie protokołu HTTPS.
Przykładowa aplikacja pokazuje, jak używać polecenia AddRedirectToHttps
lub AddRedirectToHttpsPermanent
. Utwórz niezabezpieczone żądanie HTTP do aplikacji pod adresem http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
. Podczas testowania przekierowania HTTP do HTTPS za pomocą hosta lokalnego:
- Użyj adresu URL HTTP, który ma inny port niż adres URL HTTPS. Adres URL HTTP znajduje się w
Properties/launchSettings.json
pliku . s
Usunięcie elementu zhttps://localhost/{port}
nie powiedzie się, ponieważ host lokalny nie odpowiada na porcie HTTP na port HTTPS.
Na poniższej ilustracji przedstawiono obraz narzędzi przeglądarki F12 żądania http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
użycia poprzedniego kodu:
Regenerowanie adresów URL
Użyj AddRewrite polecenia , aby utworzyć regułę na potrzeby ponownego zapisywania adresów URL. Pierwszy parametr zawiera wyrażenie regularne do dopasowywania w przychodzącej ścieżce adresu URL. Drugi parametr to ciąg zastępczy. Trzeci parametr , wskazuje oprogramowanie pośredniczące, skipRemainingRules: {true|false}
czy pominąć dodatkowe reguły ponownego zapisywania, jeśli jest stosowana bieżąca reguła.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Spróbuj wysłać żądanie do https://redirect6.azurewebsites.net/rewrite-rule/1234/5678
Daszek (^
) na początku wyrażenia oznacza, że dopasowanie rozpoczyna się na początku ścieżki adresu URL.
We wcześniejszym przykładzie z regułą redirect-rule/(.*)
przekierowania nie ma karetki (^
) na początku wyrażenia regularnego. W związku z tym wszelkie znaki mogą poprzedzać redirect-rule/
ścieżkę pomyślnego dopasowania.
Ścieżka | Match |
---|---|
/redirect-rule/1234/5678 |
Tak |
/my-cool-redirect-rule/1234/5678 |
Tak |
/anotherredirect-rule/1234/5678 |
Tak |
Reguła ponownego zapisywania, ^rewrite-rule/(\d+)/(\d+)
, pasuje tylko do ścieżek, jeśli zaczynają się od rewrite-rule/
. W poniższej tabeli zwróć uwagę na różnicę w dopasowywaniu.
Ścieżka | Match |
---|---|
/rewrite-rule/1234/5678 |
Tak |
/my-cool-rewrite-rule/1234/5678 |
Nie. |
/anotherrewrite-rule/1234/5678 |
Nie. |
^rewrite-rule/
Po części wyrażenia istnieją dwie grupy przechwytywania: (\d+)/(\d+)
. Oznacza \d
to dopasowanie cyfry (liczby). Znak plus (+
) oznacza dopasowanie co najmniej jednego z powyższych znaków. W związku z tym adres URL musi zawierać liczbę, po której następuje ukośnik do przodu, po którym następuje kolejna liczba. Te grupy przechwytywania są wstrzykiwane do przepisanego adresu URL jako $1
i $2
. Ciąg zastępczy reguły ponownej zapisywania umieszcza przechwycone grupy w ciągu zapytania. Żądana ścieżka /rewrite-rule/1234/5678
zostanie przepisana, aby zwrócić zasób pod adresem /rewritten?var1=1234&var2=5678
. Jeśli ciąg zapytania jest obecny w oryginalnym żądaniu, zostanie on zachowany, gdy adres URL zostanie przepisany.
Nie ma rundy na serwerze, aby zwrócić zasób. Jeśli zasób istnieje, jest pobierany i zwracany do klienta z kodem stanu 200 — OK . Ponieważ klient nie jest przekierowywany, adres URL na pasku adresu przeglądarki nie zmienia się. Klienci nie mogą wykryć, że na serwerze wystąpiła operacja ponownego zapisywania adresu URL.
Porady dotyczące wydajności dotyczące ponownego zapisywania i przekierowywania adresów URL
Aby uzyskać najszybszą odpowiedź:
- Kolejność ponownego zapisywania reguł z najczęściej dopasowywanej reguły do najmniej często dopasowywanej reguły.
- Używaj
skipRemainingRules: true
zawsze, gdy jest to możliwe, ponieważ pasujące reguły są kosztowne w obliczeniach i zwiększają czas odpowiedzi aplikacji. Pomiń przetwarzanie pozostałych reguł, gdy wystąpi dopasowanie i nie jest wymagane żadne dodatkowe przetwarzanie reguł.
Ostrzeżenie
Złośliwy użytkownik może zapewnić kosztowne przetwarzanie danych wejściowych w celu spowodowania RegularExpressions
ataku typu "odmowa usługi". ASP.NET podstawowe interfejsy API platformy, które używają RegularExpressions
przekroczenia limitu czasu. Na przykład klasy RedirectRule i RewriteRule przechodzą w jeden drugi limit czasu.
Apache mod_rewrite
Zastosuj reguły usługi Apache mod_rewrite za pomocą polecenia AddApacheModRewrite. Upewnij się, że plik reguł został wdrożony z aplikacją. Aby uzyskać więcej informacji i przykłady reguł mod_rewrite, zobacz Apache mod_rewrite.
Element służy StreamReader do odczytywania reguł z pliku reguł ApacheModRewrite.txt :
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Przykładowa aplikacja przekierowuje żądania z /apache-mod-rules-redirect/(.\*)
do /redirected?id=$1
. Kod stanu odpowiedzi to 302 — Znaleziono.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Spróbuj wysłać żądanie do https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234
Oprogramowanie pośredniczące Apache obsługuje następujące zmienne serwera Apache mod_rewrite:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- Protokół IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Reguły ponownego zapisywania modułów adresów URL usług IIS
Aby użyć tego samego zestawu reguł, który ma zastosowanie do modułu ponownego zapisywania adresów URL usług IIS, użyj polecenia AddIISUrlRewrite. Upewnij się, że plik reguł został wdrożony z aplikacją. Nie należy kierować oprogramowania pośredniczącego do używania pliku web.config aplikacji podczas uruchamiania w usługach IIS systemu Windows Server. W przypadku usług IIS te reguły powinny być przechowywane poza plikiem web.config aplikacji, aby uniknąć konfliktów z modułem Ponowne zapisywanie usług IIS. Aby uzyskać więcej informacji i przykłady reguł modułu ponownego zapisywania adresów URL usług IIS, zobacz Using Url Rewrite Module 2.0 and URL Rewrite Module Configuration Reference (Używanie modułu ponownego zapisywania adresów URL w wersji 2.0 ) i URL Rewrite Module Reference (Dokumentacja konfiguracji modułu ponownego zapisywania adresów URL).
Element A StreamReader służy do odczytywania reguł z IISUrlRewrite.xml
pliku reguł:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Przykładowa aplikacja ponownie zapisuje żądania z /iis-rules-rewrite/(.*)
do /rewritten?id=$1
. Odpowiedź jest wysyłana do klienta z kodem stanu 200 — OK .
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Spróbuj wysłać żądanie do https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
Aplikacje, które mają aktywny moduł ponownego zapisywania usług IIS z skonfigurowanymi regułami na poziomie serwera, które mają wpływ na aplikację w niepożądany sposób:
- Rozważ wyłączenie modułu ponownego zapisywania usług IIS dla aplikacji.
- Aby uzyskać więcej informacji, zobacz Wyłączanie modułów usług IIS.
Nieobsługiwane funkcje
Oprogramowanie pośredniczące nie obsługuje następujących funkcji modułu ponownego zapisywania adresów URL usług IIS:
- Reguły ruchu wychodzącego
- Niestandardowe zmienne serwera
- Symbole wieloznaczne
- LogRewrittenUrl
Obsługiwane zmienne serwera
Oprogramowanie pośredniczące obsługuje następujące zmienne serwera modułu ponownego zapisywania adresów URL usług IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
IFileProvidermożna uzyskać za pośrednictwem .PhysicalFileProvider Takie podejście może zapewnić większą elastyczność lokalizacji plików reguł ponownego zapisywania. Upewnij się, że pliki reguł ponownego zapisywania są wdrażane na serwerze w podanej ścieżce.
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Reguła oparta na metodzie
Służy Add do implementowania niestandardowej logiki reguł w metodzie. Add
uwidacznia element RewriteContext, który udostępnia HttpContext element do użycia w metodach przekierowania. Właściwość RewriteContext.Result określa sposób obsługi dodatkowego przetwarzania potoku. Ustaw wartość na jedno z RuleResult pól opisanych w poniższej tabeli.
Wynik ponownego zapisywania kontekstu | Akcja |
---|---|
RuleResult.ContinueRules (domyślne) |
Kontynuuj stosowanie reguł. |
RuleResult.EndResponse |
Przestań stosować reguły i wysyłać odpowiedź. |
RuleResult.SkipRemainingRules |
Przestań stosować reguły i wysyłać kontekst do następnego oprogramowania pośredniczącego. |
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Przykładowa aplikacja demonstruje metodę, która przekierowuje żądania dla ścieżek zakończonych ciągiem .xml
. Po wysłaniu żądania dla elementu /file.xml
:
- Żądanie jest przekierowywane do
/xmlfiles/file.xml
- Kod stanu jest ustawiony na
301 - Moved Permanently
wartość . Gdy przeglądarka wysyła nowe żądanie dla/xmlfiles/file.xml
programu , oprogramowanie pośredniczące plików statycznych udostępnia klientowi plik z folderu wwwroot/xmlfiles . W przypadku przekierowania jawnie ustaw kod stanu odpowiedzi. W przeciwnym razie zwracany jest kod stanu 200 — OK, a przekierowanie nie występuje na kliencie.
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")) ||
request.Path.Value==null)
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Takie podejście może również ponownie pisać żądania. Przykładowa aplikacja demonstruje ponowne zapisywanie ścieżki dla dowolnego żądania pliku tekstowego w celu obsłużenia pliku tekstowego file.txt z folderu wwwroot. Oprogramowanie pośredniczące plików statycznych obsługuje plik na podstawie zaktualizowanej ścieżki żądania:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value != null &&
request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Reguła oparta na protokole IRule
Służy Add do używania logiki reguł w klasie, która implementuje IRule interfejs. IRule
zapewnia większą elastyczność przy użyciu podejścia opartego na metodzie. Klasa implementacji może zawierać konstruktor, który umożliwia przekazywanie parametrów dla ApplyRule metody.
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
Wartości parametrów w przykładowej aplikacji dla extension
elementu i newPath
są sprawdzane pod kątem spełnienia kilku warunków. Wartość extension
musi zawierać wartość , a wartość musi mieć .png
wartość , .jpg
lub .gif
. Jeśli element newPath
jest nieprawidłowy, zostanie zgłoszony element ArgumentException . Jeśli żądanie zostanie wykonane dla image.png
elementu , żądanie zostanie przekierowane do /png-images/image.png
. Jeśli żądanie zostanie wykonane dla image.jpg
elementu , żądanie zostanie przekierowane do /jpg-images/image.jpg
. Kod stanu jest ustawiony na 301 - Moved Permanently
wartość , a context.Result
właściwość jest ustawiona na wartość , aby zatrzymać przetwarzanie reguł i wysłać odpowiedź.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)) ||
request.Path.Value == null)
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Spróbuj:
- Żądanie PNG:
https://redirect6.azurewebsites.net/image.png
- Żądanie JPG:
https://redirect6.azurewebsites.net/image.jpg
Przykłady wyrażeń regularnych
Goal | Ciąg wyrażeń regularnych i Przykład dopasowania |
Ciąg zastępczy i Przykład danych wyjściowych |
---|---|---|
Ponowne zapisywanie ścieżki do elementu querystring | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Pasek końcowy ukośnik | ^path2/(.*)/$ /path2/xyz/ |
$1 /path2/xyz |
Wymuszanie ukośnika końcowego | ^path3/(.*[^/])$ /path3/xyz |
$1/ /path3/xyz/ |
Unikaj ponownego zapisywania określonych żądań | ^(.*)(?<!\.axd)$ lub ^(?!.*\.axd$)(.*)$ Tak: /path4/resource.htm Nie: /path4/resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Ponowne rozmieszczanie segmentów adresów URL | path5/(.*)/(.*)/(.*) path5/1/2/3 |
path5/$3/$2/$1 path5/3/2/1 |
Zastępowanie segmentu adresu URL | ^path6/(.*)/segment2/(.*) ^path6/segment1/segment2/segment3 |
path6/$1/replaced/$2 /path6/segment1/replaced/segment3 |
Linki w poprzedniej tabeli używają następującego kodu wdrożonego na platformie Azure:
using Microsoft.AspNetCore.Rewrite;
using RewriteRules;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
// Rewrite path to QS.
.AddRewrite(@"^path/(.*)/(.*)", "path?var1=$1&var2=$2",
skipRemainingRules: true)
// Skip trailing slash.
.AddRewrite(@"^path2/(.*)/$", "path2/$1",
skipRemainingRules: true)
// Enforce trailing slash.
.AddRewrite(@"^path3/(.*[^/])$", "path3/$1/",
skipRemainingRules: true)
// Avoid rewriting specific requests.
.AddRewrite(@"^path4/(.*)(?<!\.axd)$", "rewritten/$1",
skipRemainingRules: true)
// Rearrange URL segments
.AddRewrite(@"^path5/(.*)/(.*)/(.*)", "path5/$3/$2/$1",
skipRemainingRules: true)
// Replace a URL segment
.AddRewrite(@"^path6/(.*)/segment2/(.*)", "path6/$1/replaced/$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
app.Run();
W większości powyższych przykładów wyrażeń regularnych literał path
jest używany do tworzenia unikatowych reguł ponownego zapisywania testowalnego dla wdrożonego przykładu. Zazwyczaj wyrażenie regularne nie zawiera path
wyrażenia regularnego. Zobacz na przykład tabelę przykładów wyrażeń regularnych .
W tym dokumencie przedstawiono ponowne zapisywanie adresów URL z instrukcjami dotyczącymi używania oprogramowania pośredniczącego ponownego zapisywania adresów URL w aplikacjach ASP.NET Core.
Ponowne zapisywanie adresów URL to czynność modyfikowania adresów URL żądań na podstawie co najmniej jednej wstępnie zdefiniowanej reguły. Ponowne zapisywanie adresów URL powoduje utworzenie abstrakcji między lokalizacjami zasobów a ich adresami, dzięki czemu lokalizacje i adresy nie są ściśle połączone. Ponowne zapisywanie adresów URL jest przydatne w kilku scenariuszach:
- Tymczasowe lub trwałe przenoszenie lub zastępowanie zasobów serwera i utrzymywanie stabilnych lokalizatorów dla tych zasobów.
- Podziel przetwarzanie żądań między różne aplikacje lub obszary jednej aplikacji.
- Usuwanie, dodawanie lub reorganizacja segmentów adresów URL dla żądań przychodzących.
- Optymalizowanie publicznych adresów URL na potrzeby optymalizacji aparatu wyszukiwania (SEO).
- Zezwól na używanie przyjaznych publicznych adresów URL, aby ułatwić odwiedzającym przewidywanie zawartości zwracanej przez żądanie zasobu.
- Przekieruj niezabezpieczone żądania do bezpiecznych punktów końcowych.
- Zapobiegaj łączeniu gorąca, w którym witryna zewnętrzna używa hostowanego zasobu statycznego w innej witrynie, łącząc zasób z własną zawartością.
Uwaga
Ponowne zapisywanie adresów URL może zmniejszyć wydajność aplikacji. W miarę możliwości ogranicz liczbę i złożoność reguł.
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Przekierowanie adresu URL i ponowne zapisywanie adresów URL
Różnica w sformułowaniu między przekierowywaniem adresów URL a ponownym zapisywaniem adresów URL jest subtelna, ale ma ważne konsekwencje dla udostępniania zasobów klientom. ASP.NET Core adres URL ponownego zapisywania oprogramowania pośredniczącego jest w stanie sprostać potrzebom obu tych programów.
Przekierowanie adresu URL obejmuje operację po stronie klienta, gdzie klient jest poinstruowany, aby uzyskać dostęp do zasobu pod innym adresem niż klient pierwotnie zażądał. Wymaga to rundy na serwerze. Adres URL przekierowania zwrócony do klienta jest wyświetlany na pasku adresu przeglądarki, gdy klient wysyła nowe żądanie dla zasobu.
Jeśli /resource
nastąpi przekierowanie do /different-resource
usługi , serwer odpowiada, że klient powinien uzyskać zasób /different-resource
z kodem stanu wskazującym, że przekierowanie jest tymczasowe lub trwałe.
Podczas przekierowywania żądań do innego adresu URL wskaż, czy przekierowanie jest trwałe, czy tymczasowe, określając kod stanu z odpowiedzią:
Kod
301 - Moved Permanently
stanu jest używany, gdy zasób ma nowy, trwały adres URL i chcesz poinstruować klienta, że wszystkie przyszłe żądania zasobu powinny używać nowego adresu URL. Klient może buforowania i ponownego użycia odpowiedzi po odebraniu kodu stanu 301.Kod stanu 302 — Znaleziono jest używany, gdy przekierowanie jest tymczasowe lub zwykle może ulec zmianie. Kod stanu 302 wskazuje klientowi, aby nie przechowywał adresu URL i używał go w przyszłości.
Aby uzyskać więcej informacji na temat kodów stanu, zobacz RFC 9110: Definicje kodu stanu.
Ponowne zapisywanie adresu URL to operacja po stronie serwera, która udostępnia zasób z innego adresu zasobu niż żądany przez klienta. Ponowne zapisywanie adresu URL nie wymaga rundy na serwerze. Przepisany adres URL nie jest zwracany do klienta i nie jest wyświetlany na pasku adresu przeglądarki.
Jeśli /resource
element zostanie przepisany do /different-resource
elementu , serwer wewnętrznie pobiera i zwraca zasób pod adresem /different-resource
.
Mimo że klient może być w stanie pobrać zasób pod adresem URL przepisanego, klient nie jest informowany, że zasób istnieje pod adresem URL przepisanym, gdy wysyła żądanie i odbiera odpowiedź.
Ponowne zapisywanie adresów URL przykładowej aplikacji
Możesz eksplorować funkcje oprogramowania pośredniczącego ponownego zapisywania adresów URL za pomocą przykładowej aplikacji. Aplikacja stosuje reguły przekierowania i ponownego zapisywania oraz wyświetla przekierowany lub przepisany adres URL w kilku scenariuszach.
Kiedy należy używać oprogramowania pośredniczącego ponownego zapisywania adresów URL
Użyj oprogramowania pośredniczącego ponownego zapisywania adresów URL, gdy nie możesz użyć następujących metod:
- Moduł ponownego zapisywania adresów URL za pomocą usług IIS w systemie Windows Server
- Moduł Apache mod_rewrite na serwerze Apache
- Ponowne zapisywanie adresów URL w usłudze Nginx
Użyj adresu URL ponownego zapisywania oprogramowania pośredniczącego, gdy aplikacja jest hostowana na serwerze HTTP.sys.
Główne przyczyny używania technologii ponownego zapisywania adresów URL opartych na serwerze w usługach IIS, Apache i Nginx są następujące:
Oprogramowanie pośredniczące nie obsługuje pełnych funkcji tych modułów.
Niektóre funkcje modułów serwera nie działają z projektami ASP.NET Core, takimi jak
IsFile
iIsDirectory
ograniczenia modułu ponownego zapisywania usług IIS. W tych scenariuszach należy zamiast tego użyć oprogramowania pośredniczącego.Wydajność oprogramowania pośredniczącego prawdopodobnie nie jest zgodna z wydajnością modułów.
Benchmarking to jedyny sposób, aby wiedzieć, które podejście obniża wydajność najbardziej lub jeśli wydajność obniżona jest nieznaczna.
Pakiet
Oprogramowanie pośredniczące ponownego zapisywania adresów URL jest dostarczane przez pakiet Microsoft.AspNetCore.Rewrite , który jest niejawnie uwzględniony w aplikacjach ASP.NET Core.
Rozszerzenia i opcje
Ustanów reguły ponownego zapisywania adresów URL i przekierowywania, tworząc wystąpienie klasy RewriteOptions przy użyciu metod rozszerzeń dla każdej reguły ponownego zapisywania. Łączenie wielu reguł w kolejności, w której mają być przetwarzane. Element RewriteOptions
jest przekazywany do adresu URL Ponowne zapisywanie oprogramowania pośredniczącego, ponieważ jest on dodawany do potoku żądania za pomocą polecenia UseRewriter:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przekieruj nie-www na www
Trzy opcje umożliwiają aplikacji przekierowywanie żądań niezwiązanychwww
z żądaniami do www
:
AddRedirectToWwwPermanent: trwałe przekierowanie żądania do
www
poddomeny, jeśli żądanie nie jestwww
. Przekierowuje za pomocą kodu stanu Status308PermanentRedirect .AddRedirectToWww: przekieruj żądanie do
www
poddomeny, jeśli żądanie przychodzące nie jestwww
. Przekierowuje z kodem stanu Status307TemporaryRedirect . Przeciążenie umożliwia podanie kodu stanu odpowiedzi. Użyj pola StatusCodes klasy do przypisania kodu stanu.
Przekierowywanie adresów URL
Służy AddRedirect do przekierowywania żądań. Pierwszy parametr zawiera wyrażenie regularne do dopasowywania na ścieżce przychodzącego adresu URL. Drugi parametr to ciąg zastępczy. Trzeci parametr, jeśli jest obecny, określa kod stanu. Jeśli nie określisz kodu stanu, kod stanu jest domyślnie ustawiony na 302 — Znaleziono, co oznacza, że zasób jest tymczasowo przenoszony lub zastępowany.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
W przeglądarce z włączonymi narzędziami deweloperskich prześlij żądanie do przykładowej aplikacji ze ścieżką /redirect-rule/1234/5678
. Wyrażenie regularne pasuje do ścieżki żądania w pliku redirect-rule/(.*)
, a ścieżka jest zastępowana ciągiem /redirected/1234/5678
. Adres URL przekierowania jest wysyłany z powrotem do klienta z kodem stanu 302 — Znaleziono . Przeglądarka wysyła nowe żądanie pod adresem URL przekierowania, które jest wyświetlane na pasku adresu przeglądarki. Ponieważ w adresie URL przekierowania nie są zgodne żadne reguły w przykładowej aplikacji:
- Drugie żądanie odbiera odpowiedź 200 — OK z aplikacji.
- Treść odpowiedzi zawiera adres URL przekierowania.
Podczas przekierowywania adresu URL następuje zaokrąglenie do serwera.
Ostrzeżenie
Podczas ustanawiania reguł przekierowania należy zachować ostrożność. Reguły przekierowania są oceniane dla każdego żądania do aplikacji, w tym po przekierowaniu. Łatwo jest przypadkowo utworzyć pętlę nieskończonych przekierowań.
Oryginalne żądanie: /redirect-rule/1234/5678
Część wyrażenia zawartego w nawiasach jest nazywana grupą przechwytywania. Kropka (.
) wyrażenia oznacza dopasowanie dowolnego znaku. Gwiazdka (*
) wskazuje dopasowanie poprzedniego znaku zero lub więcej razy. W związku z tym ostatnie dwa segmenty ścieżki adresu URL są 1234/5678
przechwytywane przez grupę (.*)
przechwytywania . Każda wartość, którą podajesz w adresie URL żądania po redirect-rule/
przechwyceniu przez tę pojedynczą grupę przechwytywania.
W ciągu zastępczym przechwycone grupy są wstrzykiwane do ciągu znakiem dolara ($
), a następnie numerem sekwencji przechwytywania. Pierwsza wartość grupy przechwytywania jest uzyskiwana za pomocą $1
elementu , drugiego z elementami $2
i są one kontynuowane w sekwencji dla grup przechwytywania w regex. W przykładowej aplikacji istnieje tylko jedna przechwycona grupa w regex reguły przekierowania, więc w ciągu zastępczym znajduje się tylko jedna grupa wstrzyknięta, czyli $1
. Po zastosowaniu reguły adres URL zmieni się na /redirected/1234/5678
.
Przekierowanie adresu URL do bezpiecznego punktu końcowego
Użyj polecenia AddRedirectToHttps , aby przekierować żądania HTTP do tego samego hosta i ścieżki przy użyciu protokołu HTTPS. Jeśli kod stanu nie zostanie podany, oprogramowanie pośredniczące domyślnie ma wartość 302 — Znaleziono. Jeśli port nie jest podany:
- Domyślnie oprogramowanie pośredniczące ma wartość
null
. - Schemat zmienia się na
https
(protokół HTTPS), a klient uzyskuje dostęp do zasobu na porcie 443.
W poniższym przykładzie pokazano, jak ustawić kod stanu na 301 - Moved Permanently
i zmienić port na 5001.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Służy AddRedirectToHttpsPermanent do przekierowywania niezabezpieczonych żądań do tego samego hosta i ścieżki przy użyciu bezpiecznego protokołu HTTPS na porcie 443. Oprogramowanie pośredniczące ustawia kod stanu na 301 - Moved Permanently
.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Uwaga
Podczas przekierowywania do bezpiecznego punktu końcowego bez wymagania dodatkowych reguł przekierowania zalecamy użycie oprogramowania pośredniczącego przekierowania HTTPS. Aby uzyskać więcej informacji, zobacz temat Wymuszanie protokołu HTTPS .
Przykładowa aplikacja może pokazać, jak używać AddRedirectToHttps
metody lub AddRedirectToHttpsPermanent
. Dodaj metodę rozszerzenia do klasy RewriteOptions
. Utwórz niezabezpieczone żądanie do aplikacji pod dowolnym adresem URL. Odrzuć ostrzeżenie o zabezpieczeniach przeglądarki, że certyfikat z podpisem własnym jest niezaufany lub utwórz wyjątek, aby ufać certyfikatowi.
Oryginalne żądanie przy użyciu polecenia AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Oryginalne żądanie przy użyciu polecenia AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Regenerowanie adresów URL
Użyj AddRewrite polecenia , aby utworzyć regułę na potrzeby ponownego zapisywania adresów URL. Pierwszy parametr zawiera wyrażenie regularne do dopasowywania w przychodzącej ścieżce adresu URL. Drugi parametr to ciąg zastępczy. Trzeci parametr , wskazuje oprogramowanie pośredniczące, skipRemainingRules: {true|false}
czy pominąć dodatkowe reguły ponownego zapisywania, jeśli jest stosowana bieżąca reguła.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Oryginalne żądanie: /rewrite-rule/1234/5678
Karat (^
) na początku wyrażenia oznacza, że dopasowanie rozpoczyna się na początku ścieżki adresu URL.
We wcześniejszym przykładzie z regułą redirect-rule/(.*)
przekierowania nie ma karata (^
) na początku regexu. W związku z tym wszelkie znaki mogą poprzedzać redirect-rule/
ścieżkę pomyślnego dopasowania.
Ścieżka | Match |
---|---|
/redirect-rule/1234/5678 |
Tak |
/my-cool-redirect-rule/1234/5678 |
Tak |
/anotherredirect-rule/1234/5678 |
Tak |
Reguła ponownego zapisywania, ^rewrite-rule/(\d+)/(\d+)
, pasuje tylko do ścieżek, jeśli zaczynają się od rewrite-rule/
. W poniższej tabeli zwróć uwagę na różnicę w dopasowywaniu.
Ścieżka | Match |
---|---|
/rewrite-rule/1234/5678 |
Tak |
/my-cool-rewrite-rule/1234/5678 |
Nie. |
/anotherrewrite-rule/1234/5678 |
Nie. |
^rewrite-rule/
Po części wyrażenia istnieją dwie grupy przechwytywania: (\d+)/(\d+)
. Oznacza \d
to dopasowanie cyfry (liczby). Znak plus (+
) oznacza dopasowanie co najmniej jednego z powyższych znaków. W związku z tym adres URL musi zawierać liczbę, po której następuje ukośnik do przodu, po którym następuje kolejna liczba. Te grupy przechwytywania są wstrzykiwane do przepisanego adresu URL jako $1
i $2
. Ciąg zastępczy reguły ponownej zapisywania umieszcza przechwycone grupy w ciągu zapytania. Żądana ścieżka elementu /rewrite-rule/1234/5678
zostanie przepisana, aby uzyskać zasób pod adresem /rewritten?var1=1234&var2=5678
. Jeśli ciąg zapytania jest obecny w oryginalnym żądaniu, zostanie on zachowany, gdy adres URL zostanie przepisany.
Nie ma rundy na serwerze, aby uzyskać zasób. Jeśli zasób istnieje, jest pobierany i zwracany do klienta z kodem stanu 200 — OK . Ponieważ klient nie jest przekierowywany, adres URL na pasku adresu przeglądarki nie zmienia się. Klienci nie mogą wykryć, że na serwerze wystąpiła operacja ponownego zapisywania adresu URL.
Uwaga
Używaj skipRemainingRules: true
zawsze, gdy jest to możliwe, ponieważ pasujące reguły są kosztowne w obliczeniach i zwiększają czas odpowiedzi aplikacji. Aby uzyskać najszybszą odpowiedź na aplikację:
- Kolejność ponownego zapisywania reguł z najczęściej dopasowywanej reguły do najmniej często dopasowywanej reguły.
- Pomiń przetwarzanie pozostałych reguł, gdy wystąpi dopasowanie i nie jest wymagane żadne dodatkowe przetwarzanie reguł.
Apache mod_rewrite
Zastosuj reguły usługi Apache mod_rewrite za pomocą polecenia AddApacheModRewrite. Upewnij się, że plik reguł został wdrożony z aplikacją. Aby uzyskać więcej informacji i przykłady reguł mod_rewrite, zobacz Apache mod_rewrite.
Element służy StreamReader do odczytywania reguł z pliku reguł ApacheModRewrite.txt :
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przykładowa aplikacja przekierowuje żądania z /apache-mod-rules-redirect/(.\*)
do /redirected?id=$1
. Kod stanu odpowiedzi to 302 — Znaleziono.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Oryginalne żądanie: /apache-mod-rules-redirect/1234
Oprogramowanie pośredniczące obsługuje następujące zmienne serwera Apache mod_rewrite:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- Protokół IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Reguły ponownego zapisywania modułów adresów URL usług IIS
Aby użyć tego samego zestawu reguł, który ma zastosowanie do modułu ponownego zapisywania adresów URL usług IIS, użyj polecenia AddIISUrlRewrite. Upewnij się, że plik reguł został wdrożony z aplikacją. Nie należy kierować oprogramowania pośredniczącego do używania pliku web.config aplikacji podczas uruchamiania w usługach IIS systemu Windows Server. W przypadku usług IIS te reguły powinny być przechowywane poza plikiem web.config aplikacji, aby uniknąć konfliktów z modułem Ponowne zapisywanie usług IIS. Aby uzyskać więcej informacji i przykłady reguł modułu ponownego zapisywania adresów URL usług IIS, zobacz Using Url Rewrite Module 2.0 and URL Rewrite Module Configuration Reference (Używanie modułu ponownego zapisywania adresów URL w wersji 2.0 ) i URL Rewrite Module Reference (Dokumentacja konfiguracji modułu ponownego zapisywania adresów URL).
Element A StreamReader służy do odczytywania reguł z IISUrlRewrite.xml
pliku reguł:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przykładowa aplikacja ponownie zapisuje żądania z /iis-rules-rewrite/(.*)
do /rewritten?id=$1
. Odpowiedź jest wysyłana do klienta z kodem stanu 200 — OK .
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Oryginalne żądanie: /iis-rules-rewrite/1234
Jeśli masz aktywny moduł ponownego zapisywania usług IIS z skonfigurowanymi regułami na poziomie serwera, które będą miały wpływ na aplikację w niepożądany sposób, możesz wyłączyć moduł ponownego zapisywania usług IIS dla aplikacji. Aby uzyskać więcej informacji, zobacz Wyłączanie modułów usług IIS.
Nieobsługiwane funkcje
Oprogramowanie pośredniczące nie obsługuje następujących funkcji modułu ponownego zapisywania adresów URL usług IIS:
- Reguły ruchu wychodzącego
- Niestandardowe zmienne serwera
- Symbole wieloznaczne
- LogRewrittenUrl
Obsługiwane zmienne serwera
Oprogramowanie pośredniczące obsługuje następujące zmienne serwera modułu ponownego zapisywania adresów URL usług IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Uwaga
Możesz również uzyskać element IFileProvider za pośrednictwem elementu PhysicalFileProvider. Takie podejście może zapewnić większą elastyczność lokalizacji plików reguł ponownego zapisywania. Upewnij się, że pliki reguł ponownego zapisywania są wdrażane na serwerze w podanej ścieżce.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Reguła oparta na metodzie
Użyj Add polecenia , aby zaimplementować własną logikę reguł w metodzie . Add
uwidacznia element RewriteContext, który udostępnia HttpContext element do użycia w metodzie . RewriteContext.Result określa sposób obsługi dodatkowego przetwarzania potoku. Ustaw wartość na jedno z RuleResult pól opisanych w poniższej tabeli.
Wynik ponownego zapisywania kontekstu | Akcja |
---|---|
RuleResult.ContinueRules (domyślne) |
Kontynuuj stosowanie reguł. |
RuleResult.EndResponse |
Przestań stosować reguły i wysyłać odpowiedź. |
RuleResult.SkipRemainingRules |
Przestań stosować reguły i wysyłać kontekst do następnego oprogramowania pośredniczącego. |
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przykładowa aplikacja demonstruje metodę, która przekierowuje żądania dla ścieżek zakończonych ciągiem .xml
. Jeśli żądanie zostanie wykonane dla /file.xml
elementu , żądanie zostanie przekierowane do /xmlfiles/file.xml
. Kod stanu jest ustawiony na 301 - Moved Permanently
wartość . Gdy przeglądarka wysyła nowe żądanie dla /xmlfiles/file.xml
programu , oprogramowanie pośredniczące plików statycznych udostępnia klientowi plik z folderu wwwroot/xmlfiles . W przypadku przekierowania jawnie ustaw kod stanu odpowiedzi. W przeciwnym razie zwracany jest kod stanu 200 — OK, a przekierowanie nie występuje na kliencie.
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Takie podejście może również ponownie pisać żądania. Przykładowa aplikacja demonstruje ponowne zapisywanie ścieżki dla dowolnego żądania pliku tekstowego w celu obsłużenia pliku tekstowego file.txt z folderu wwwroot. Oprogramowanie pośredniczące plików statycznych obsługuje plik na podstawie zaktualizowanej ścieżki żądania:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Reguła oparta na protokole IRule
Służy Add do używania logiki reguł w klasie, która implementuje IRule interfejs. IRule
zapewnia większą elastyczność przy użyciu podejścia opartego na metodzie. Klasa implementacji może zawierać konstruktor, który umożliwia przekazywanie parametrów dla ApplyRule metody .
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Wartości parametrów w przykładowej aplikacji dla extension
elementu i newPath
są sprawdzane pod kątem spełnienia kilku warunków. Wartość extension
musi zawierać wartość, a wartość musi być .png
wartością , .jpg
lub .gif. Jeśli element newPath
jest nieprawidłowy, zostanie zgłoszony element ArgumentException . Jeśli żądanie zostanie wykonane dla image.png
elementu , żądanie zostanie przekierowane do /png-images/image.png
. Jeśli żądanie zostanie wykonane dla image.jpg
elementu , żądanie zostanie przekierowane do /jpg-images/image.jpg
. Kod stanu jest ustawiony na 301 - Moved Permanently
wartość , a context.Result
właściwość jest ustawiona na wartość , aby zatrzymać przetwarzanie reguł i wysłać odpowiedź.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Oryginalne żądanie: /image.png
Oryginalne żądanie: /image.jpg
Przykłady wyrażeń regularnych
Goal | Ciąg wyrażeń regularnych i Przykład dopasowania |
Ciąg zastępczy i Przykład danych wyjściowych |
---|---|---|
Ponowne zapisywanie ścieżki do elementu querystring | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Pasek końcowy ukośnik | (.*)/$ /path/ |
$1 /path |
Wymuszanie ukośnika końcowego | (.*[^/])$ /path |
$1/ /path/ |
Unikaj ponownego zapisywania określonych żądań | ^(.*)(?<!\.axd)$ lub ^(?!.*\.axd$)(.*)$ Tak: /resource.htm Nie: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Ponowne rozmieszczanie segmentów adresów URL | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Zastępowanie segmentu adresu URL | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
W tym dokumencie przedstawiono ponowne zapisywanie adresów URL z instrukcjami dotyczącymi używania oprogramowania pośredniczącego ponownego zapisywania adresów URL w aplikacjach ASP.NET Core.
Ponowne zapisywanie adresów URL to czynność modyfikowania adresów URL żądań na podstawie co najmniej jednej wstępnie zdefiniowanej reguły. Ponowne zapisywanie adresów URL powoduje utworzenie abstrakcji między lokalizacjami zasobów a ich adresami, dzięki czemu lokalizacje i adresy nie są ściśle połączone. Ponowne zapisywanie adresów URL jest przydatne w kilku scenariuszach:
- Tymczasowe lub trwałe przenoszenie lub zastępowanie zasobów serwera i utrzymywanie stabilnych lokalizatorów dla tych zasobów.
- Podziel przetwarzanie żądań między różne aplikacje lub obszary jednej aplikacji.
- Usuwanie, dodawanie lub reorganizacja segmentów adresów URL dla żądań przychodzących.
- Optymalizowanie publicznych adresów URL na potrzeby optymalizacji aparatu wyszukiwania (SEO).
- Zezwól na używanie przyjaznych publicznych adresów URL, aby ułatwić odwiedzającym przewidywanie zawartości zwracanej przez żądanie zasobu.
- Przekieruj niezabezpieczone żądania do bezpiecznych punktów końcowych.
- Zapobiegaj łączeniu gorąca, w którym witryna zewnętrzna używa hostowanego zasobu statycznego w innej witrynie, łącząc zasób z własną zawartością.
Uwaga
Ponowne zapisywanie adresów URL może zmniejszyć wydajność aplikacji. W miarę możliwości ogranicz liczbę i złożoność reguł.
Wyświetl lub pobierz przykładowy kod (jak pobrać)
Przekierowanie adresu URL i ponowne zapisywanie adresów URL
Różnica w sformułowaniu między przekierowywaniem adresów URL a ponownym zapisywaniem adresów URL jest subtelna, ale ma ważne konsekwencje dla udostępniania zasobów klientom. ASP.NET Core adres URL ponownego zapisywania oprogramowania pośredniczącego jest w stanie sprostać potrzebom obu tych programów.
Przekierowanie adresu URL obejmuje operację po stronie klienta, gdzie klient jest poinstruowany, aby uzyskać dostęp do zasobu pod innym adresem niż klient pierwotnie zażądał. Wymaga to rundy na serwerze. Adres URL przekierowania zwrócony do klienta jest wyświetlany na pasku adresu przeglądarki, gdy klient wysyła nowe żądanie dla zasobu.
Jeśli /resource
nastąpi przekierowanie do /different-resource
usługi , serwer odpowiada, że klient powinien uzyskać zasób /different-resource
z kodem stanu wskazującym, że przekierowanie jest tymczasowe lub trwałe.
Podczas przekierowywania żądań do innego adresu URL wskaż, czy przekierowanie jest trwałe, czy tymczasowe, określając kod stanu z odpowiedzią:
Kod
301 - Moved Permanently
stanu jest używany, gdy zasób ma nowy, trwały adres URL i chcesz poinstruować klienta, że wszystkie przyszłe żądania zasobu powinny używać nowego adresu URL. Klient może buforowania i ponownego użycia odpowiedzi po odebraniu kodu stanu 301.Kod stanu 302 — Znaleziono jest używany, gdy przekierowanie jest tymczasowe lub zwykle może ulec zmianie. Kod stanu 302 wskazuje klientowi, aby nie przechowywał adresu URL i używał go w przyszłości.
Aby uzyskać więcej informacji na temat kodów stanu, zobacz RFC 9110: Definicje kodu stanu.
Ponowne zapisywanie adresu URL to operacja po stronie serwera, która udostępnia zasób z innego adresu zasobu niż żądany przez klienta. Ponowne zapisywanie adresu URL nie wymaga rundy na serwerze. Przepisany adres URL nie jest zwracany do klienta i nie jest wyświetlany na pasku adresu przeglądarki.
Jeśli /resource
element zostanie przepisany do /different-resource
elementu , serwer wewnętrznie pobiera i zwraca zasób pod adresem /different-resource
.
Mimo że klient może być w stanie pobrać zasób pod adresem URL przepisanego, klient nie jest informowany, że zasób istnieje pod adresem URL przepisanym, gdy wysyła żądanie i odbiera odpowiedź.
Ponowne zapisywanie adresów URL przykładowej aplikacji
Możesz eksplorować funkcje oprogramowania pośredniczącego ponownego zapisywania adresów URL za pomocą przykładowej aplikacji. Aplikacja stosuje reguły przekierowania i ponownego zapisywania oraz wyświetla przekierowany lub przepisany adres URL w kilku scenariuszach.
Kiedy należy używać oprogramowania pośredniczącego ponownego zapisywania adresów URL
Użyj oprogramowania pośredniczącego ponownego zapisywania adresów URL, gdy nie możesz użyć następujących metod:
- Moduł ponownego zapisywania adresów URL za pomocą usług IIS w systemie Windows Server
- Moduł Apache mod_rewrite na serwerze Apache
- Ponowne zapisywanie adresów URL w usłudze Nginx
Ponadto należy użyć oprogramowania pośredniczącego, gdy aplikacja jest hostowana na serwerze HTTP.sys (dawniej o nazwie WebListener).
Główne przyczyny używania technologii ponownego zapisywania adresów URL opartych na serwerze w usługach IIS, Apache i Nginx są następujące:
Oprogramowanie pośredniczące nie obsługuje pełnych funkcji tych modułów.
Niektóre funkcje modułów serwera nie działają z projektami ASP.NET Core, takimi jak
IsFile
iIsDirectory
ograniczenia modułu ponownego zapisywania usług IIS. W tych scenariuszach należy zamiast tego użyć oprogramowania pośredniczącego.Wydajność oprogramowania pośredniczącego prawdopodobnie nie jest zgodna z wydajnością modułów.
Benchmarking to jedyny sposób, aby wiedzieć, które podejście obniża wydajność najbardziej lub jeśli wydajność obniżona jest nieznaczna.
Pakiet
Aby uwzględnić oprogramowanie pośredniczące w projekcie, dodaj odwołanie do pakietu Microsoft.AspNetCore.App metapakietu w pliku projektu, który zawiera pakiet Microsoft.AspNetCore.Rewrite .
Jeśli nie używasz Microsoft.AspNetCore.App
metapakiet, dodaj odwołanie do projektu do Microsoft.AspNetCore.Rewrite
pakietu.
Rozszerzenia i opcje
Ustanów reguły ponownego zapisywania adresów URL i przekierowywania, tworząc wystąpienie klasy RewriteOptions przy użyciu metod rozszerzeń dla każdej reguły ponownego zapisywania. Łączenie wielu reguł w kolejności, w której mają być przetwarzane. Element RewriteOptions
jest przekazywany do adresu URL Ponowne zapisywanie oprogramowania pośredniczącego, ponieważ jest on dodawany do potoku żądania za pomocą polecenia UseRewriter:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przekieruj nie-www na www
Trzy opcje umożliwiają aplikacji przekierowywanie żądań niezwiązanychwww
z żądaniami do www
:
AddRedirectToWwwPermanent: trwałe przekierowanie żądania do
www
poddomeny, jeśli żądanie nie jestwww
. Przekierowuje za pomocą kodu stanu Status308PermanentRedirect .AddRedirectToWww: przekieruj żądanie do
www
poddomeny, jeśli żądanie przychodzące nie jestwww
. Przekierowuje z kodem stanu Status307TemporaryRedirect . Przeciążenie umożliwia podanie kodu stanu odpowiedzi. Użyj pola StatusCodes klasy do przypisania kodu stanu.
Przekierowywanie adresów URL
Służy AddRedirect do przekierowywania żądań. Pierwszy parametr zawiera wyrażenie regularne do dopasowywania na ścieżce przychodzącego adresu URL. Drugi parametr to ciąg zastępczy. Trzeci parametr, jeśli jest obecny, określa kod stanu. Jeśli nie określisz kodu stanu, kod stanu jest domyślnie ustawiony na 302 — Znaleziono, co oznacza, że zasób jest tymczasowo przenoszony lub zastępowany.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
W przeglądarce z włączonymi narzędziami deweloperskich prześlij żądanie do przykładowej aplikacji ze ścieżką /redirect-rule/1234/5678
. Wyrażenie regularne pasuje do ścieżki żądania w pliku redirect-rule/(.*)
, a ścieżka jest zastępowana ciągiem /redirected/1234/5678
. Adres URL przekierowania jest wysyłany z powrotem do klienta z kodem stanu 302 — Znaleziono . Przeglądarka wysyła nowe żądanie pod adresem URL przekierowania, które jest wyświetlane na pasku adresu przeglądarki. Ponieważ w adresie URL przekierowania nie są zgodne żadne reguły w przykładowej aplikacji:
- Drugie żądanie odbiera odpowiedź 200 — OK z aplikacji.
- Treść odpowiedzi zawiera adres URL przekierowania.
Podczas przekierowywania adresu URL następuje zaokrąglenie do serwera.
Ostrzeżenie
Podczas ustanawiania reguł przekierowania należy zachować ostrożność. Reguły przekierowania są oceniane dla każdego żądania do aplikacji, w tym po przekierowaniu. Łatwo jest przypadkowo utworzyć pętlę nieskończonych przekierowań.
Oryginalne żądanie: /redirect-rule/1234/5678
Część wyrażenia zawartego w nawiasach jest nazywana grupą przechwytywania. Kropka (.
) wyrażenia oznacza dopasowanie dowolnego znaku. Gwiazdka (*
) wskazuje dopasowanie poprzedniego znaku zero lub więcej razy. W związku z tym ostatnie dwa segmenty ścieżki adresu URL są 1234/5678
przechwytywane przez grupę (.*)
przechwytywania . Każda wartość, którą podajesz w adresie URL żądania po redirect-rule/
przechwyceniu przez tę pojedynczą grupę przechwytywania.
W ciągu zastępczym przechwycone grupy są wstrzykiwane do ciągu znakiem dolara ($
), a następnie numerem sekwencji przechwytywania. Pierwsza wartość grupy przechwytywania jest uzyskiwana za pomocą $1
elementu , drugiego z elementami $2
i są one kontynuowane w sekwencji dla grup przechwytywania w regex. W przykładowej aplikacji istnieje tylko jedna przechwycona grupa w regex reguły przekierowania, więc w ciągu zastępczym znajduje się tylko jedna grupa wstrzyknięta, czyli $1
. Po zastosowaniu reguły adres URL zmieni się na /redirected/1234/5678
.
Przekierowanie adresu URL do bezpiecznego punktu końcowego
Użyj polecenia AddRedirectToHttps , aby przekierować żądania HTTP do tego samego hosta i ścieżki przy użyciu protokołu HTTPS. Jeśli kod stanu nie zostanie podany, oprogramowanie pośredniczące domyślnie ma wartość 302 — Znaleziono. Jeśli port nie jest podany:
- Domyślnie oprogramowanie pośredniczące ma wartość
null
. - Schemat zmienia się na
https
(protokół HTTPS), a klient uzyskuje dostęp do zasobu na porcie 443.
W poniższym przykładzie pokazano, jak ustawić kod stanu na 301 - Moved Permanently
i zmienić port na 5001.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Służy AddRedirectToHttpsPermanent do przekierowywania niezabezpieczonych żądań do tego samego hosta i ścieżki przy użyciu bezpiecznego protokołu HTTPS na porcie 443. Oprogramowanie pośredniczące ustawia kod stanu na 301 - Moved Permanently
.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Uwaga
Podczas przekierowywania do bezpiecznego punktu końcowego bez wymagania dodatkowych reguł przekierowania zalecamy użycie oprogramowania pośredniczącego przekierowania HTTPS. Aby uzyskać więcej informacji, zobacz temat Wymuszanie protokołu HTTPS .
Przykładowa aplikacja może pokazać, jak używać AddRedirectToHttps
metody lub AddRedirectToHttpsPermanent
. Dodaj metodę rozszerzenia do klasy RewriteOptions
. Utwórz niezabezpieczone żądanie do aplikacji pod dowolnym adresem URL. Odrzuć ostrzeżenie o zabezpieczeniach przeglądarki, że certyfikat z podpisem własnym jest niezaufany lub utwórz wyjątek, aby ufać certyfikatowi.
Oryginalne żądanie przy użyciu polecenia AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Oryginalne żądanie przy użyciu polecenia AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Regenerowanie adresów URL
Użyj AddRewrite polecenia , aby utworzyć regułę na potrzeby ponownego zapisywania adresów URL. Pierwszy parametr zawiera wyrażenie regularne do dopasowywania w przychodzącej ścieżce adresu URL. Drugi parametr to ciąg zastępczy. Trzeci parametr , wskazuje oprogramowanie pośredniczące, skipRemainingRules: {true|false}
czy pominąć dodatkowe reguły ponownego zapisywania, jeśli jest stosowana bieżąca reguła.
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Oryginalne żądanie: /rewrite-rule/1234/5678
Karat (^
) na początku wyrażenia oznacza, że dopasowanie rozpoczyna się na początku ścieżki adresu URL.
We wcześniejszym przykładzie z regułą redirect-rule/(.*)
przekierowania nie ma karata (^
) na początku regexu. W związku z tym wszelkie znaki mogą poprzedzać redirect-rule/
ścieżkę pomyślnego dopasowania.
Ścieżka | Match |
---|---|
/redirect-rule/1234/5678 |
Tak |
/my-cool-redirect-rule/1234/5678 |
Tak |
/anotherredirect-rule/1234/5678 |
Tak |
Reguła ponownego zapisywania, ^rewrite-rule/(\d+)/(\d+)
, pasuje tylko do ścieżek, jeśli zaczynają się od rewrite-rule/
. W poniższej tabeli zwróć uwagę na różnicę w dopasowywaniu.
Ścieżka | Match |
---|---|
/rewrite-rule/1234/5678 |
Tak |
/my-cool-rewrite-rule/1234/5678 |
Nie. |
/anotherrewrite-rule/1234/5678 |
Nie. |
^rewrite-rule/
Po części wyrażenia istnieją dwie grupy przechwytywania: (\d+)/(\d+)
. Oznacza \d
to dopasowanie cyfry (liczby). Znak plus (+
) oznacza dopasowanie co najmniej jednego z powyższych znaków. W związku z tym adres URL musi zawierać liczbę, po której następuje ukośnik do przodu, po którym następuje kolejna liczba. Te grupy przechwytywania są wstrzykiwane do przepisanego adresu URL jako $1
i $2
. Ciąg zastępczy reguły ponownej zapisywania umieszcza przechwycone grupy w ciągu zapytania. Żądana ścieżka elementu /rewrite-rule/1234/5678
zostanie przepisana, aby uzyskać zasób pod adresem /rewritten?var1=1234&var2=5678
. Jeśli ciąg zapytania jest obecny w oryginalnym żądaniu, zostanie on zachowany, gdy adres URL zostanie przepisany.
Nie ma rundy na serwerze, aby uzyskać zasób. Jeśli zasób istnieje, jest pobierany i zwracany do klienta z kodem stanu 200 — OK . Ponieważ klient nie jest przekierowywany, adres URL na pasku adresu przeglądarki nie zmienia się. Klienci nie mogą wykryć, że na serwerze wystąpiła operacja ponownego zapisywania adresu URL.
Uwaga
Używaj skipRemainingRules: true
zawsze, gdy jest to możliwe, ponieważ pasujące reguły są kosztowne w obliczeniach i zwiększają czas odpowiedzi aplikacji. Aby uzyskać najszybszą odpowiedź na aplikację:
- Kolejność ponownego zapisywania reguł z najczęściej dopasowywanej reguły do najmniej często dopasowywanej reguły.
- Pomiń przetwarzanie pozostałych reguł, gdy wystąpi dopasowanie i nie jest wymagane żadne dodatkowe przetwarzanie reguł.
Apache mod_rewrite
Zastosuj reguły usługi Apache mod_rewrite za pomocą polecenia AddApacheModRewrite. Upewnij się, że plik reguł został wdrożony z aplikacją. Aby uzyskać więcej informacji i przykłady reguł mod_rewrite, zobacz Apache mod_rewrite.
Element służy StreamReader do odczytywania reguł z pliku reguł ApacheModRewrite.txt :
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przykładowa aplikacja przekierowuje żądania z /apache-mod-rules-redirect/(.\*)
do /redirected?id=$1
. Kod stanu odpowiedzi to 302 — Znaleziono.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Oryginalne żądanie: /apache-mod-rules-redirect/1234
Oprogramowanie pośredniczące obsługuje następujące zmienne serwera Apache mod_rewrite:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- Protokół IPV6
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_METHOD
- REQUEST_SCHEME
- REQUEST_URI
- SCRIPT_FILENAME
- SERVER_ADDR
- SERVER_PORT
- SERVER_PROTOCOL
- TIME
- TIME_DAY
- TIME_HOUR
- TIME_MIN
- TIME_MON
- TIME_SEC
- TIME_WDAY
- TIME_YEAR
Reguły ponownego zapisywania modułów adresów URL usług IIS
Aby użyć tego samego zestawu reguł, który ma zastosowanie do modułu ponownego zapisywania adresów URL usług IIS, użyj polecenia AddIISUrlRewrite. Upewnij się, że plik reguł został wdrożony z aplikacją. Nie należy kierować oprogramowania pośredniczącego do używania pliku web.config aplikacji podczas uruchamiania w usługach IIS systemu Windows Server. W przypadku usług IIS te reguły powinny być przechowywane poza plikiem web.config aplikacji, aby uniknąć konfliktów z modułem Ponowne zapisywanie usług IIS. Aby uzyskać więcej informacji i przykłady reguł modułu ponownego zapisywania adresów URL usług IIS, zobacz Using Url Rewrite Module 2.0 and URL Rewrite Module Configuration Reference (Używanie modułu ponownego zapisywania adresów URL w wersji 2.0 ) i URL Rewrite Module Reference (Dokumentacja konfiguracji modułu ponownego zapisywania adresów URL).
Element A StreamReader służy do odczytywania reguł z IISUrlRewrite.xml
pliku reguł:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przykładowa aplikacja ponownie zapisuje żądania z /iis-rules-rewrite/(.*)
do /rewritten?id=$1
. Odpowiedź jest wysyłana do klienta z kodem stanu 200 — OK .
<rewrite>
<rules>
<rule name="Rewrite segment to id querystring" stopProcessing="true">
<match url="^iis-rules-rewrite/(.*)$" />
<action type="Rewrite" url="rewritten?id={R:1}" appendQueryString="false"/>
</rule>
</rules>
</rewrite>
Oryginalne żądanie: /iis-rules-rewrite/1234
Jeśli masz aktywny moduł ponownego zapisywania usług IIS z skonfigurowanymi regułami na poziomie serwera, które będą miały wpływ na aplikację w niepożądany sposób, możesz wyłączyć moduł ponownego zapisywania usług IIS dla aplikacji. Aby uzyskać więcej informacji, zobacz Wyłączanie modułów usług IIS.
Nieobsługiwane funkcje
Oprogramowanie pośredniczące wydane za pomocą ASP.NET Core 2.x nie obsługuje następujących funkcji modułu ponownego zapisywania adresów URL usług IIS:
- Reguły ruchu wychodzącego
- Niestandardowe zmienne serwera
- Symbole wieloznaczne
- LogRewrittenUrl
Obsługiwane zmienne serwera
Oprogramowanie pośredniczące obsługuje następujące zmienne serwera modułu ponownego zapisywania adresów URL usług IIS:
- CONTENT_LENGTH
- CONTENT_TYPE
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_HOST
- HTTP_REFERER
- HTTP_URL
- HTTP_USER_AGENT
- HTTPS
- LOCAL_ADDR
- QUERY_STRING
- REMOTE_ADDR
- REMOTE_PORT
- REQUEST_FILENAME
- REQUEST_URI
Uwaga
Możesz również uzyskać element IFileProvider za pośrednictwem elementu PhysicalFileProvider. Takie podejście może zapewnić większą elastyczność lokalizacji plików reguł ponownego zapisywania. Upewnij się, że pliki reguł ponownego zapisywania są wdrażane na serwerze w podanej ścieżce.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Reguła oparta na metodzie
Użyj Add polecenia , aby zaimplementować własną logikę reguł w metodzie . Add
uwidacznia element RewriteContext, który udostępnia HttpContext element do użycia w metodzie . RewriteContext.Result określa sposób obsługi dodatkowego przetwarzania potoku. Ustaw wartość na jedno z RuleResult pól opisanych w poniższej tabeli.
Wynik ponownego zapisywania kontekstu | Akcja |
---|---|
RuleResult.ContinueRules (domyślne) |
Kontynuuj stosowanie reguł. |
RuleResult.EndResponse |
Przestań stosować reguły i wysyłać odpowiedź. |
RuleResult.SkipRemainingRules |
Przestań stosować reguły i wysyłać kontekst do następnego oprogramowania pośredniczącego. |
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Przykładowa aplikacja demonstruje metodę, która przekierowuje żądania dla ścieżek zakończonych ciągiem .xml
. Jeśli żądanie zostanie wykonane dla /file.xml
elementu , żądanie zostanie przekierowane do /xmlfiles/file.xml
. Kod stanu jest ustawiony na 301 - Moved Permanently
wartość . Gdy przeglądarka wysyła nowe żądanie dla /xmlfiles/file.xml
programu , oprogramowanie pośredniczące plików statycznych udostępnia klientowi plik z folderu wwwroot/xmlfiles . W przypadku przekierowania jawnie ustaw kod stanu odpowiedzi. W przeciwnym razie zwracany jest kod stanu 200 — OK, a przekierowanie nie występuje na kliencie.
RewriteRules.cs
:
public static void RedirectXmlFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because the client is redirecting back to the same app, stop
// processing if the request has already been redirected.
if (request.Path.StartsWithSegments(new PathString("/xmlfiles")))
{
return;
}
if (request.Path.Value.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
"/xmlfiles" + request.Path + request.QueryString;
}
}
Takie podejście może również ponownie pisać żądania. Przykładowa aplikacja demonstruje ponowne zapisywanie ścieżki dla dowolnego żądania pliku tekstowego w celu obsłużenia pliku tekstowego file.txt z folderu wwwroot. Oprogramowanie pośredniczące plików statycznych obsługuje plik na podstawie zaktualizowanej ścieżki żądania:
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
RewriteRules.cs
:
public static void RewriteTextFileRequests(RewriteContext context)
{
var request = context.HttpContext.Request;
if (request.Path.Value.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
context.Result = RuleResult.SkipRemainingRules;
request.Path = "/file.txt";
}
}
Reguła oparta na protokole IRule
Służy Add do używania logiki reguł w klasie, która implementuje IRule interfejs. IRule
zapewnia większą elastyczność przy użyciu podejścia opartego na metodzie. Klasa implementacji może zawierać konstruktor, który umożliwia przekazywanie parametrów dla ApplyRule metody .
public void Configure(IApplicationBuilder app)
{
using (StreamReader apacheModRewriteStreamReader =
File.OpenText("ApacheModRewrite.txt"))
using (StreamReader iisUrlRewriteStreamReader =
File.OpenText("IISUrlRewrite.xml"))
{
var options = new RewriteOptions()
.AddRedirect("redirect-rule/(.*)", "redirected/$1")
.AddRewrite(@"^rewrite-rule/(\d+)/(\d+)", "rewritten?var1=$1&var2=$2",
skipRemainingRules: true)
.AddApacheModRewrite(apacheModRewriteStreamReader)
.AddIISUrlRewrite(iisUrlRewriteStreamReader)
.Add(MethodRules.RedirectXmlFileRequests)
.Add(MethodRules.RewriteTextFileRequests)
.Add(new RedirectImageRequests(".png", "/png-images"))
.Add(new RedirectImageRequests(".jpg", "/jpg-images"));
app.UseRewriter(options);
}
app.UseStaticFiles();
app.Run(context => context.Response.WriteAsync(
$"Rewritten or Redirected Url: " +
$"{context.Request.Path + context.Request.QueryString}"));
}
Wartości parametrów w przykładowej aplikacji dla extension
elementu i newPath
są sprawdzane pod kątem spełnienia kilku warunków. Wartość extension
musi zawierać wartość, a wartość musi być .png
wartością , .jpg
lub .gif. Jeśli element newPath
jest nieprawidłowy, zostanie zgłoszony element ArgumentException . Jeśli żądanie zostanie wykonane dla image.png
elementu , żądanie zostanie przekierowane do /png-images/image.png
. Jeśli żądanie zostanie wykonane dla image.jpg
elementu , żądanie zostanie przekierowane do /jpg-images/image.jpg
. Kod stanu jest ustawiony na 301 - Moved Permanently
wartość , a context.Result
właściwość jest ustawiona na wartość , aby zatrzymać przetwarzanie reguł i wysłać odpowiedź.
public class RedirectImageRequests : IRule
{
private readonly string _extension;
private readonly PathString _newPath;
public RedirectImageRequests(string extension, string newPath)
{
if (string.IsNullOrEmpty(extension))
{
throw new ArgumentException(nameof(extension));
}
if (!Regex.IsMatch(extension, @"^\.(png|jpg|gif)$"))
{
throw new ArgumentException("Invalid extension", nameof(extension));
}
if (!Regex.IsMatch(newPath, @"(/[A-Za-z0-9]+)+?"))
{
throw new ArgumentException("Invalid path", nameof(newPath));
}
_extension = extension;
_newPath = new PathString(newPath);
}
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
// Because we're redirecting back to the same app, stop
// processing if the request has already been redirected
if (request.Path.StartsWithSegments(new PathString(_newPath)))
{
return;
}
if (request.Path.Value.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
{
var response = context.HttpContext.Response;
response.StatusCode = (int) HttpStatusCode.MovedPermanently;
context.Result = RuleResult.EndResponse;
response.Headers[HeaderNames.Location] =
_newPath + request.Path + request.QueryString;
}
}
}
Oryginalne żądanie: /image.png
Oryginalne żądanie: /image.jpg
Przykłady wyrażeń regularnych
Goal | Ciąg wyrażeń regularnych i Przykład dopasowania |
Ciąg zastępczy i Przykład danych wyjściowych |
---|---|---|
Ponowne zapisywanie ścieżki do elementu querystring | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Pasek końcowy ukośnik | (.*)/$ /path/ |
$1 /path |
Wymuszanie ukośnika końcowego | (.*[^/])$ /path |
$1/ /path/ |
Unikaj ponownego zapisywania określonych żądań | ^(.*)(?<!\.axd)$ lub ^(?!.*\.axd$)(.*)$ Tak: /resource.htm Nie: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Ponowne rozmieszczanie segmentów adresów URL | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Zastępowanie segmentu adresu URL | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
Dodatkowe zasoby
- Wyświetl lub pobierz przykładowy kod (jak pobrać)
- Ponowne zapisywanie źródła oprogramowaniaMiddleware w usłudze GitHub
- Uruchamianie aplikacji na platformie ASP.NET Core
- oprogramowanie pośredniczące ASP.NET Core
- Wyrażenia regularne na platformie .NET
- Język wyrażeń regularnych — krótki przewodnik
- Apache mod_rewrite
- Używanie modułu ponownego zapisywania adresów URL 2.0 (dla usług IIS)
- Dokumentacja konfiguracji modułu ponownego zapisywania adresów URL
- Zachowaj prostą strukturę adresów URL
- 10 Porad i wskazówki dotyczące ponownego zapisywania adresów URL
- Ukośnik lub nie ukośnik