URL-umschreibende Middleware in ASP.NET Core
Hinweis
Dies ist nicht die neueste Version dieses Artikels. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Warnung
Diese Version von ASP.NET Core wird nicht mehr unterstützt. Weitere Informationen finden Sie in der .NET- und .NET Core-Supportrichtlinie. Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Wichtig
Diese Informationen beziehen sich auf ein Vorabversionsprodukt, das vor der kommerziellen Freigabe möglicherweise noch wesentlichen Änderungen unterliegt. Microsoft gibt keine Garantie, weder ausdrücklich noch impliziert, hinsichtlich der hier bereitgestellten Informationen.
Die aktuelle Version finden Sie in der .NET 9-Version dieses Artikels.
Von Kirk Larkin und Rick Anderson
In diesem Artikel wird das Neuschreiben von URLs beschrieben. Außerdem erhalten Sie Anweisungen zur Verwendung von Middleware zum Neuschreiben von URLs in ASP.NET Core-Apps.
Bei der URL-Umschreibung werden die Anforderungs-URLs verändert, die auf mindesten einer vordefinierten Regel basieren. Es wird eine Abstraktion zwischen den Speicherorten und Adressen von Ressourcen erstellt, sodass diese nicht eng miteinander verknüpft sind. Die URL-Neuschreibung ist hilfreich in verschiedenen Szenarios wie:
- Kurzzeitiges oder permanentes Verschieben oder Ersetzen von Serverressourcen, sowie Erhalten von stabilen Locators für diese Ressourcen.
- Verteilen der Verarbeitung von Anforderungen auf verschiedene Apps oder Bereiche einer App.
- Entfernen, Hinzufügen oder Umorganisieren von URL-Segmenten bei eingehenden Anforderungen.
- Optimieren von öffentlichen URLs für die Suchmaschinenoptimierung (Search Engine Optimization, SEO).
- Gestatten der Verwendung von angezeigten öffentlichen URLs, um Besuchern zu helfen, den Inhalt vorherzusagen, der durch die Anforderung einer Ressource zurückgegeben wird.
- Umleiten von unsicheren Anforderungen auf sichere Endpunkte.
- Verhindern von Hotlinks zu externen Websites, die eine gehostete statische Ressource auf einer anderen Website verwenden, bei der die Ressource zu ihrem eigenen Inhalt verlinkt wird.
Wenn Sie URLs neu schreiben, kann das negative Auswirkungen auf die Leistung einer App haben. Sie sollten so wenig Regeln wie möglich erstellen und darauf achten, dass diese nicht zu komplex sind.
Umleiten und Umschreiben von URLs
Der Unterschied zwischen dem Umleiten und Neu schreiben von URLs ist zwar gering, allerdings haben die beiden Verfahren sehr unterschiedliche Auswirkungen auf die Bereitstellung von Ressourcen für Clients. Die URL-umschreibenden Middleware von ASP.NET Core kann für beide Vorgänge verwendet werden.
Bei der Umleitung von URLs findet ein clientseitiger Vorgang statt, bei dem der Client angewiesen wird, auf eine Ressource unter einer anderen Adresse zuzugreifen, als die, die der Client ursprünglich angefordert hat. Dafür ist ein Roundtrip zum Server erforderlich. Die Umleitungs-URL, die an den Client zurückgegeben wird, wird in der Adressleiste des Browsers angezeigt, wenn der Client eine neue Anforderung an die Ressource sendet.
Wenn /resource
auf /different-resource
umgeleitet wird, sendet der Server die Antwort, dass der Client die Ressource unter /different-resource
abrufen soll. In der Antwort ist außerdem ein Statuscode enthalten, aus dem entnommen werden kann, ob die Umleitung temporär oder permanent ist.
Wenn Anforderungen auf eine andere URL umgeleitet werden, muss angegeben werden, ob die Umleitung temporär oder permanent sein soll. Geben Sie hierzu den Statuscode mit der Antwort an:
Der Statuscode
301 - Moved Permanently
wird verwendet, wenn der Ressource eine neue permanente URL zugewiesen wurde und alle zukünftigen Anforderungen an die Ressource die neue URL verwenden sollen. Der Client kann die Antwort zwischenspeichern und wiederverwenden, wenn der Statuscode 301 empfangen wird.Der Statuscode
302 - Found
wird verwendet, wenn die Umleitung temporär ist oder sowieso Änderungen vorbehalten sind. Der Statuscode 302 teilt dem Client mit, dass die URL nicht gespeichert und nicht wiederverwendet werden soll.
Weitere Informationen zu Statuscodes finden Sie unter RFC 9110: Statuscodedefinitionen.
Bei der Neuschreibung einer URL handelt es sich um einen serverseitigen Vorgang, bei dem eine Ressource von einer anderen Ressourcenadresse, als der vom Client angeforderten, bereitgestellt wird. Wenn eine URL neu geschrieben wird, ist kein Roundtrip zum Server erforderlich. Die neu geschriebene URL wird nicht an den Server zurückgegeben und nicht in der Adressleiste des Browsers angezeigt.
Wenn /resource
in /different-resource
umgeschrieben wird, ruft der Server die Ressource intern ab und gibt sie zurück an /different-resource
.
Auch wenn der Client die Ressource unter der neu geschriebene URL abrufen kann, erhält er nicht die Information, dass die Ressource unter der umgeschriebenen URL gespeichert ist, wenn er die Anforderung sendet und eine Antwort erhält.
URL-umschreibende Beispiel-App
Mit der Beispiel-App können Sie die Features der Middleware zum Neuschreiben von URLs testen. Die App wendet Umleitungs- und Neuschreibungsregeln an und zeigt die umgeleitete oder neu geschriebene URL für verschiedene Szenarios an.
Empfohlene Verwendung der Middleware zum Neuschreiben von URLs
Verwenden Sie Middleware zur URL-Neuschreibung, wenn die folgenden Ansätze nicht ausreichend sind:
- URL Rewrite module with IIS on Windows Server (URL-Neuschreibungsmodul mit IIS auf Windows-Server)
- Apache mod_rewrite module on Apache Server (Apache mod_rewrite-Modul auf Apache-Server)
- URL rewriting on Nginx (URL-Neuschreibung auf Nginx)
Verwenden Sie die Middleware für URL-Neuschreibung, wenn die Anwendung auf dem HTTP.sys-Server gehostet wird.
Die Hauptgründe für die Verwendung der serverbasierten Technologien zur URL-Neuschreibung in IIS, Apache und Nginx sind:
Die Middleware unterstützt nicht alle Features dieser Module.
Einige Features der Servermodule funktionieren nicht mit ASP.NET Core-Projekten – z.B. die Einschränkungen
IsFile
undIsDirectory
des IIS-Neuschreibungsmoduls. Verwenden Sie in diesem Szenario stattdessen die Middleware.Die Leistung der Middleware stimmt wahrscheinlich nicht mit der Leistung der Module überein.
Benchmarking ist der einzige Weg, um sicher festzustellen, welcher Ansatz die Leistung am meisten beeinträchtigt oder ob die nachlassende Leistung nur geringfügig ist.
Erweiterung und Optionen
Legen Sie Regeln für URL-Neuschreibung und -Umleitung fest, indem Sie eine Instanz der RewriteOptions-Klasse erstellen und Erweiterungsmethoden für jede Neuschreibungsregel hinzufügen. Verketten Sie mehrere Regeln in der Reihenfolge, in der sie verarbeitet werden sollen. Die RewriteOptions
werden an die Middleware zur URL-Neuschreibung übergeben, wenn diese mit UseRewriter zu der Anforderungspipeline hinzugefügt wird:
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();
Im vorherigen Code ist MethodRules
eine benutzerdefinierte Klasse. Weitere Informationen finden Sie unter RewriteRules.cs
in diesem Artikel.
Umleitung einer Nicht-WWW-Anforderung an eine WWW-Anforderung
Drei Optionen ermöglichen der App, Nicht-www
-Anforderungen an www
umzuleiten:
AddRedirectToWwwPermanent: Die Anforderung wird dauerhaft an die Unterdomäne
www
umgeleitet, sofern die Anforderung nichtwww
ist. Wird mit dem Statuscode Status308PermanentRedirect umgeleitet.AddRedirectToWww: Die Anforderung wird an die Unterdomäne
www
umgeleitet, sofern die eingehende Anforderung nichtwww
ist. Wird mit dem Statuscode Status307TemporaryRedirect umgeleitet. Eine Überladung ermöglicht es, den Statuscode für die Antwort zu senden. Verwenden Sie ein Feld der StatusCodes-Klasse, um einen Statuscode zuzuweisen.
Umleitungs-URL
Verwenden Sie AddRedirect, um Anforderungen umzuleiten. Der erste Parameter enthält den regulären .NET-Ausdruck (RegEx) für die Zuordnung zum Pfad der eingehenden URL. Beim zweiten Parameter handelt es sich um eine Ersatzzeichenfolge. Der dritte Parameter gibt, falls vorhanden, den Statuscode an. Wenn der Statuscode nicht angegeben wird, wird standardmäßig 302 – Gefunden zurückgegeben. Dies bedeutet, dass die Ressource vorübergehend verschoben oder ersetzt wurde.
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();
Aktivieren Sie in Ihrem Browser die Entwicklertools, und senden Sie eine Anforderung an die Beispiel-App mit dem Pfad /redirect-rule/1234/5678
. Der reguläre Ausdruck stimmt mit dem Anforderungspfad unter redirect-rule/(.*)
überein, und der Pfad wird durch /redirected/1234/5678
ersetzt. Die Umleitungs-URL wird mit dem Statuscode 302 – Gefunden an den Client zurückgesendet. Unter der Umleitungs-URL sendet der Browser eine neue Anforderung, die in dessen Adressleiste angezeigt wird. Da keine Regel in der Beispiel-App mit der Umleitungs-URL übereinstimmt:
- Die zweite Anforderung erhält die Antwort 200 – OK von der App.
- Der Antworttext zeigt die Umleitungs-URL an.
Wenn eine URL weitergeleitet wird, wird ein Roundtrip zum Server ausgelöst.
Warnung
Seien Sie vorsichtig, wenn Sie Umleitungsregeln einrichten. Bei jeder Anforderung an die App werden Umleitungsregeln überprüft – auch nach einer Umleitung. Dabei kann schnell aus Versehen eine Dauerschleife von Umleitungen entstehen.
Der Teil des Ausdruck in Klammern wird als Erfassungsgruppe bezeichnet. Der Punkt (.
) im Ausdruck steht für Übereinstimmung mit beliebigem Zeichen. Das Sternchen (*
) steht für Übereinstimmung mit dem vorausgehenden Zeichen (keinmal oder mindestens einmal) . Daher werden die letzten beiden Pfadsegmente der URL (1234/5678
) von der Erfassungsgruppe erfasst (.*)
. Alle Werte, die in der Anforderungs-URL nach redirect-rule/
angegeben werden, werden von dieser Erfassungsgruppe erfasst.
Erfassungsgruppen werden in der Ersetzungszeichenfolge mit dem Dollarzeichen ($
) in die Zeichenfolge eingefügt. Danach folgt die Sequenznummer der Erfassung. Der erste Wert der Erfassungsgruppe wird mit $1
abgerufen, der zweite mit $2
. Dies wird in Sequenzen für die Erfassungsgruppen im regulären Ausdruck weitergeführt. Es gibt nur eine erfasste Gruppe im regulären Ausdruck der Umleitungsregel in redirect-rule/(.*)
, also gibt es auch nur eine injizierte Gruppe in der Ersetzungszeichenfolge, nämlich $1
. Wenn die Regel angewendet wird, ändert sich die URL in /redirected/1234/5678
.
Versuchen Sie /redirect-rule/1234/5678
mit den Browsertools auf der Registerkarte „Netzwerk“.
URL-Umleitung an einen sicheren Endpunkt
Verwenden Sie AddRedirectToHttps, um HTTP-Anforderungen auf denselben Host und Pfad mithilfe des HTTPS-Protokolls umzuleiten. Wenn kein Statuscode angegeben wird, wird für die Middleware standardmäßig 302 – Gefunden zurückgegeben. Wenn kein Port angegeben ist:
- Für die Middleware wird standardmäßig
null
zurückgegeben. - Das Schema ändert sich in
https
(HTTPS-Protokoll), und der Client hat über Port 443 Zugriff auf die Ressource.
Das folgende Beispiel zeigt, wie Sie den Statuscode auf 301 - Moved Permanently
festlegen und den Port in den HTTPS-Port ändern, der von Kestrel auf localhost verwendet wird. In der Produktion ist der HTTPS-Port auf NULL festgelegt:
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();
Verwenden Sie AddRedirectToHttpsPermanent, um unsichere Anforderungen auf denselben Host und Pfad mit einem sicheren HTTPS-Protokoll auf Port 443 umzuleiten. Die Middleware legt den Statuscode auf 301 - Moved Permanently
fest.
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();
Hinweis
Wenn Sie eine Umleitung an einen sicheren Endpunkt ohne weitere erforderliche Umleitungsregeln durchführen, wird empfohlen, Middleware für HTTPS-Umleitung zu verwenden. Weitere Informationen finden Sie unter Erzwingen von HTTPS.
Die Beispiel-App veranschaulicht, wie AddRedirectToHttps
oder AddRedirectToHttpsPermanent
verwendet wird. Senden Sie eine unsichere Anforderung an die App unter http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
. Beim Testen der Umleitung von HTTP zu HTTPS mit localhost:
- Verwenden Sie die HTTP-URL, die über einen anderen Port als die HTTPS-URL verfügt. Die HTTP-URL befindet sich in der Datei
Properties/launchSettings.json
. - Das Entfernen von
s
aushttps://localhost/{port}
schlägt fehl, da localhost dem HTTPS-Port nicht über HTTP antwortet.
Die folgende Abbildung zeigt die F12-Browsertools mit einer Anforderung an http://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
mithilfe des Codes oben:
Umschreiben einer URL
Erstellen Sie mithilfe von AddRewrite eine Regel zum Umschreiben von URLs. Der erste Parameter enthält den regulären Ausdruck für die Zuordnung zum Pfad der eingehenden URL. Beim zweiten Parameter handelt es sich um eine Ersatzzeichenfolge. Der dritte Parameter (skipRemainingRules: {true|false}
) teilt der Middleware mit, ob sie zusätzliche Umschreibungsregeln überspringen soll, wenn die aktuelle Regel angewendet wird.
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();
Ausprobieren der Anforderung an https://redirect6.azurewebsites.net/rewrite-rule/1234/5678
Das Zirkumflexzeichen (^
) am Anfang des Ausdrucks bedeutet, dass die Übereinstimmung schon am Anfang des URL-Pfads beginnt.
In dem vorherigen Beispiel zu den Umleitungsregeln, redirect-rule/(.*)
, beginnt der reguläre Ausdruck nicht mit einem Zirkumflexzeichen (^
). So kann für eine Übereinstimmung ein beliebiges Zeichen im Pfad vor redirect-rule/
stehen.
Pfad | Match |
---|---|
/redirect-rule/1234/5678 |
Ja |
/my-cool-redirect-rule/1234/5678 |
Ja |
/anotherredirect-rule/1234/5678 |
Ja |
Die Umschreibungsregel (^rewrite-rule/(\d+)/(\d+)
) stimmt nur mit Pfaden überein, wenn sie mit rewrite-rule/
beginnen. Beachten Sie die unterschiedliche Übereinstimmung in der folgenden Tabelle:
Pfad | Match |
---|---|
/rewrite-rule/1234/5678 |
Ja |
/my-cool-rewrite-rule/1234/5678 |
Nr. |
/anotherrewrite-rule/1234/5678 |
Nein |
Auf den ^rewrite-rule/
-Teil des Ausdruck folgen zwei Erfassungsgruppen: (\d+)/(\d+)
. \d
steht für Übereinstimmung mit einer Ziffer (Zahl) . Das Pluszeichen (+
) steht für match one or more of the preceding character (Übereinstimmung mit mindestens einem vorausgehenden Zeichen). Aus diesem Grund muss die URL eine Zahl enthalten, auf die ein Schrägstrich und eine weitere Zahl folgt. Die Erfassungsgruppen werden in die umgeschriebene URL als $1
und $2
eingefügt. Über die Ersetzungszeichenfolge der Neuschreibungsregel werden die Erfassungsgruppen in die Abfragezeichenfolge eingefügt. Der angeforderte /rewrite-rule/1234/5678
-Pfad wird neu geschrieben, um die Ressource unter /rewritten?var1=1234&var2=5678
zurückzugeben. Wenn es in der ursprünglichen Anforderung eine Abfragezeichenfolge gibt, bleibt diese erhalten, wenn die URL umgeschrieben wird.
Es gibt keinen Roundtrip zum Server, um die Ressource zurückzugeben. Wenn es die Ressource gibt, wird sie abgerufen und dem Client mit dem Statuscode 200 – OK zurückgegeben. Da der Client nicht umgeleitet wird, ändert sich die URL in der Adressleiste des Browsers nicht. Clients können nicht erkennen, dass ein Vorgang zum erneuten Schreiben einer URL auf dem Server stattgefunden hat.
Leistungstipps zum Neuschreiben und Umleiten von URLs
Führen Sie folgende Schritte aus, um die schnellsten Antwortzeiten zu erreichen:
- Sortieren Sie Neuschreibungsregeln von der am häufigsten abgeglichenen Regel zu der am seltensten abgeglichenen Regel.
- Verwenden Sie
skipRemainingRules: true
, wo immer das möglich ist, da das Abgleichen von Regeln rechnerisch sehr aufwendig ist und die Antwortzeit der App erhöht. Überspringen Sie die Verarbeitung der übrigen Regeln, wenn es zu einer Übereinstimmung kommt und keine zusätzlichen Regelverarbeitungen erforderlich sind.
Warnung
Ein böswilliger Benutzer kann verarbeitungsintensive Eingaben für RegularExpressions
angeben, um einen Denial-of-Service-Angriff durchzuführen. ASP.NET Core-Framework-APIs, die RegularExpressions
verwenden, übergeben ein Timeout. Beispielsweise übergeben die RedirectRule- und RewriteRule-Klassen ein Timeout von einer Sekunde.
Apache: „mod_rewrite“
Wenden Sie die Apache-Regeln „mod_rewrite“ mit AddApacheModRewrite an. Vergewissern Sie sich, dass die Regeldatei mit der App bereitgestellt wird. Weitere Informationen zu diesen Regeln finden Sie unter Apache: „mod_rewrite“.
Zum Lesen der Regeldatei ApacheModRewrite.txt wird StreamReader verwendet:
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();
Die Beispiel-App leitet Anforderungen von /apache-mod-rules-redirect/(.\*)
auf /redirected?id=$1
um. Der Antwortstatuscode lautet 302 – Gefunden.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Ausprobieren der Anforderung an https://redirect6.azurewebsites.net/apache-mod-rules-redirect/1234
Die Apache-Middleware unterstützt die folgenden mod_rewrite-Servervariablen von Apache:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- 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
Regeln zum IIS-Umschreibungsmodul
Um denselben Regelsatz zu verwenden, der für das IIS-Moduls für URL-Neuschreibung gilt, verwenden Sie AddIISUrlRewrite. Vergewissern Sie sich, dass die Regeldatei mit der App bereitgestellt wird. Geben Sie der Middleware nicht die Anweisung, die web.config-Datei der App zu verwenden, wenn sie auf der Windows Server-IIS ausgeführt wird. Bei IIS sollten diese Regeln außerhalb der web.config-Datei der App gespeichert werden, um Konflikte mit dem IIS-Neuschreibungsmodul zu vermeiden. Weitere Informationen und Beispiele zu den Regeln zum IIS-Umschreibungsmodul finden Sie unter Using Url Rewrite Module 2.0 (Verwenden des URL-Umschreibungsmoduls 2.0) und URL Rewrite Module Configuration Reference (Konfigurationsreferenz des URL-Umschreibungsmoduls).
Zum Lesen der Regeldatei IISUrlRewrite.xml
wird StreamReader verwendet:
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();
Die Beispiel-App schreibt Anforderungen von /iis-rules-rewrite/(.*)
in /rewritten?id=$1
um. Die Antwort wird an den Client mit dem Statuscode 200 – OK gesendet.
<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>
Ausprobieren der Anforderung an https://redirect6.azurewebsites.net/iis-rules-rewrite/xyz
Für Apps, die über ein aktives IIS-Neuschreibungsmodul mit konfigurierten Regeln auf Serverebene verfügen, das die App in unerwünschter Weise beeinfluss, gilt Folgendes:
- Erwägen Sie, das IIS-Neuschreibungsmodul für die App zu deaktivieren.
- Weitere Informationen finden Sie unter Disabling IIS modules (Deaktivieren von IIS-Modulen).
Nicht unterstützte Features
Die Middleware unterstützt die folgenden Features des IIS-URL-Umschreibungsmoduls nicht:
- Ausgehende Regeln
- Benutzerdefinierte Servervariablen
- Platzhalter
- LogRewrittenUrl
Unterstützte Servervariablen
Die Middleware unterstützt die folgenden Servervariablen für das IIS-URL-Neuschreibungsmodul:
- 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
IFileProvider kann über einen PhysicalFileProvider abgerufen werden. Über diesen Ansatz können Sie flexibler einen Speicherort für die Dateien der Neuschreibungsregeln auswählen. Vergewissern Sie sich, dass die Dateien zu den Neuschreibungsregeln auf dem Server unter dem von Ihnen angegebenen Pfad bereitgestellt werden.
var fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Methodenbasierte Regel
Verwenden Sie Add, um benutzerdefinierte Regellogik in einer Methode zu implementieren. Add
macht RewriteContext verfügbar, wodurch die Verwendung von HttpContext in Umleitungsmethoden ermöglicht wird. Die RewriteContext.Result-Eigenschaft bestimmt, wie zusätzliche Pipelineverarbeitung erfolgt. Legen Sie den Wert auf eines der RuleResult-Felder fest, die in der folgenden Tabelle beschrieben sind:
Umschreiben von Kontext – Ergebnisse | Aktion |
---|---|
RuleResult.ContinueRules (Standardwert) |
Regeln weiter anwenden. |
RuleResult.EndResponse |
Regeln nicht mehr anwenden und Antwort senden. |
RuleResult.SkipRemainingRules |
Regeln nicht mehr anwenden, und den Kontext an die nächste Middleware senden. |
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();
In der Beispiel-App wird eine Methode dargestellt, die Anforderungen für Pfade weiterleitet, die auf .xml
enden. Wenn eine Anforderung für /file.xml
gesendet wird:
- Die Anforderung wird an
/xmlfiles/file.xml
umgeleitet. - Der Statuscode wird auf
301 - Moved Permanently
festgelegt. Wenn vom Browser eine neue Anforderung für/xmlfiles/file.xml
gesendet wird, wird dem Client die Datei von Middleware für statische Dateien aus dem Ordner wwwroot/xmlfiles bereitgestellt. Legen Sie für eine Umleitung den Statuscode der Antwort explizit fest. Andernfalls wird ein Statuscode 200 – OK zurückgegeben, und die Umleitung findet nicht auf dem Client statt.
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;
}
}
Bei diesem Ansatz können auch Anforderungen erneut generiert werden. In der Beispiel-App wird demonstriert, wie der Pfad für eine beliebige Textdateianforderung umgeschrieben wird, um die Textdatei file.txt aus dem Ordner wwwroot bereitzustellen. Middleware für statische Dateien stellt die Datei bereit, die auf dem aktualisierten Anforderungspfad basiert:
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";
}
}
IRule-basierte Regel
Um Regellogik in einer Klasse zu nutzen, die die IRule-Schnittstelle implementiert, verwenden Sie Add. Wenn Sie IRule
verwenden, können Sie flexibler entscheiden, ob Sie eine methodenbasierte Regel verwenden möchten. Die Implementierungsklasse kann einen Konstruktor enthalten, wodurch Parameter für die ApplyRule-Methode übergeben werden können.
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();
Die Werte für die Parameter in der Beispiel-App für extension
und newPath
werden auf verschiedene Bedingungen geprüft. extension
muss einen Wert enthalten, der .png
, .jpg
oder .gif
entspricht. Wenn newPath
nicht gültig ist, wird ArgumentException nicht ausgelöst. Wenn eine Anforderung für image.png
erfolgt, wird sie zu /png-images/image.png
umgeleitet. Wenn eine Anforderung für image.jpg
erfolgt, wird sie zu /jpg-images/image.jpg
umgeleitet. Der Statuscode wird auf 301 - Moved Permanently
festgelegt, und context.Result
erhält die Anweisung, Verarbeitungsregeln zu beenden und die Antwort zu senden.
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;
}
}
}
Versuchen Sie das:
- PNG-Anforderung:
https://redirect6.azurewebsites.net/image.png
- JPG-Anforderung:
https://redirect6.azurewebsites.net/image.jpg
RegEx-Beispiele
Ziel | RegEx-Zeichenfolge und übereinstimmendes Beispiel |
Ersetzungszeichenfolge und Ausgabebeispiel |
---|---|---|
Umschreiben des Pfads in die Abfragezeichenfolge | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Entfernen des nachgestellten Schrägstrichs | ^path2/(.*)/$ /path2/xyz/ |
$1 /path2/xyz |
Erzwingen des nachgestellten Schrägstrichs | ^path3/(.*[^/])$ /path3/xyz |
$1/ /path3/xyz/ |
Vermeiden des Umschreibens von bestimmten Anforderungen | ^(.*)(?<!\.axd)$ oder ^(?!.*\.axd$)(.*)$ Ja: /path4/resource.htm Nein: /path4/resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Ändern der Anordnung von URL-Segmenten | path5/(.*)/(.*)/(.*) path5/1/2/3 |
path5/$3/$2/$1 path5/3/2/1 |
Ersetzen von URL-Segmenten | ^path6/(.*)/segment2/(.*) ^path6/segment1/segment2/segment3 |
path6/$1/replaced/$2 /path6/segment1/replaced/segment3 |
Die Links in der Tabelle oben verwenden den folgenden Code, der in Azure bereitgestellt wird:
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();
In den meisten vorherigen Beispielen für reguläre Ausdrücke wird das Literal path
verwendet, um eindeutige testbare Neuschreibungsregeln für das bereitgestellte Beispiel zu erstellen. In der Regel würde der reguläre Ausdruck path
nicht enthalten. Sehen Sie sich beispielsweise diese Tabelle mit Beispielen für reguläre Ausdrücke an.
In diesem Artikel wird das Umschreiben von URLs beschrieben. Außerdem erhalten Sie Anweisungen zur Verwendung der URL-umschreibenden Middleware in ASP.NET Core-Apps.
Bei der URL-Umschreibung werden die Anforderungs-URLs verändert, die auf mindesten einer vordefinierten Regel basieren. Es wird eine Abstraktion zwischen den Speicherorten und Adressen von Ressourcen erstellt, sodass diese nicht eng miteinander verknüpft sind. Die URL-Neuschreibung ist hilfreich in verschiedenen Szenarios wie:
- Kurzzeitiges oder permanentes Verschieben oder Ersetzen von Serverressourcen, sowie Erhalten von stabilen Locators für diese Ressourcen.
- Verteilen der Verarbeitung von Anforderungen auf verschiedene Apps oder Bereiche einer App.
- Entfernen, Hinzufügen oder Umorganisieren von URL-Segmenten bei eingehenden Anforderungen.
- Optimieren von öffentlichen URLs für die Suchmaschinenoptimierung (Search Engine Optimization, SEO).
- Gestatten der Verwendung von angezeigten öffentlichen URLs, um Besuchern zu helfen, den Inhalt vorherzusagen, der durch die Anforderung einer Ressource zurückgegeben wird.
- Umleiten von unsicheren Anforderungen auf sichere Endpunkte.
- Verhindern von Hotlinks zu externen Websites, die eine gehostete statische Ressource auf einer anderen Website verwenden, bei der die Ressource zu ihrem eigenen Inhalt verlinkt wird.
Hinweis
Wenn Sie URLs umschreiben, kann das negative Auswirkungen auf die Leistung einer App haben. Wenn möglich, sollten Sie so wenig Regeln wie möglich erstellen und darauf achten, dass diese nicht zu kompliziert sind.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Umleiten und Umschreiben von URLs
Der Unterschied zwischen dem Umleiten und Neu schreiben von URLs ist zwar gering, allerdings haben die beiden Verfahren sehr unterschiedliche Auswirkungen auf die Bereitstellung von Ressourcen für Clients. Die URL-umschreibenden Middleware von ASP.NET Core kann für beide Vorgänge verwendet werden.
Bei der Umleitung von URLs findet ein clientseitiger Vorgang statt, bei dem der Client angewiesen wird, auf eine Ressource unter einer anderen Adresse zuzugreifen, als die, die der Client ursprünglich angefordert hat. Dafür ist ein Roundtrip zum Server erforderlich. Die Umleitungs-URL, die an den Client zurückgegeben wird, wird in der Adressleiste des Browsers angezeigt, wenn der Client eine neue Anforderung an die Ressource sendet.
Wenn /resource
auf /different-resource
umgeleitet wird, sendet der Server die Antwort, dass der Client die Ressource unter /different-resource
abrufen soll. In der Antwort ist außerdem ein Statuscode enthalten, aus dem entnommen werden kann, ob die Umleitung temporär oder permanent ist.
Wenn Anforderungen auf eine andere URL umgeleitet werden, muss angegeben werden, ob die Umleitung temporär oder permanent sein soll. Geben Sie hierzu den Statuscode mit der Antwort an:
Der Statuscode
301 - Moved Permanently
wird verwendet, wenn der Ressource eine neue permanente URL zugewiesen wurde, und Sie dem Client die Anweisung geben möchten, dass alle zukünftigen Anforderungen an die Ressource die neue URL verwenden sollen. Der Client kann die Antwort zwischenspeichern und wiederverwenden, wenn der Statuscode 301 empfangen wird.Der Statuscode 302 – Gefunden wird verwendet, wenn die Umleitung temporär ist oder sowieso Änderungen vorbehalten sind. Der Statuscode 302 teilt dem Client mit, dass die URL nicht gespeichert und nicht wiederverwendet werden soll.
Weitere Informationen zu Statuscodes finden Sie unter RFC 9110: Statuscodedefinitionen.
Bei der Neuschreibung einer URL handelt es sich um einen serverseitigen Vorgang, bei dem eine Ressource von einer anderen Ressourcenadresse, als der vom Client angeforderten, bereitgestellt wird. Wenn eine URL neu geschrieben wird, ist kein Roundtrip zum Server erforderlich. Die neu geschriebene URL wird nicht an den Server zurückgegeben und nicht in der Adressleiste des Browsers angezeigt.
Wenn /resource
in /different-resource
umgeschrieben wird, ruft der Server die Ressource intern ab und gibt sie zurück an /different-resource
.
Auch wenn der Client die Ressource unter der neu geschriebene URL abrufen kann, erhält er nicht die Information, dass die Ressource unter der umgeschriebenen URL gespeichert ist, wenn er die Anforderung sendet und eine Antwort erhält.
URL-umschreibende Beispiel-App
Mit der Beispiel-App können Sie die Features der Middleware zur URL-Neuschreibung testen. Die App wendet Umleitungs- und Neuschreibungsregeln an und zeigt die umgeleitete oder neu geschriebene URL für verschiedene Szenarios an.
Empfohlene Verwendung der Middleware zum Neuschreiben von URLs
Sie können Middleware zur URL-Neuschreibung verwenden, wenn die folgenden Ansätze nicht möglich sind:
- URL Rewrite module with IIS on Windows Server (URL-Neuschreibungsmodul mit IIS auf Windows-Server)
- Apache mod_rewrite module on Apache Server (Apache mod_rewrite-Modul auf Apache-Server)
- URL rewriting on Nginx (URL-Neuschreibung auf Nginx)
Verwenden Sie die Middleware für URL-Neuschreibung, wenn die Anwendung auf dem HTTP.sys-Server gehostet wird.
Die Hauptgründe für die Verwendung der serverbasierten Technologien zur URL-Neuschreibung in IIS, Apache und Nginx sind:
Die Middleware unterstützt nicht alle Features dieser Module.
Einige Features der Servermodule funktionieren nicht mit ASP.NET Core-Projekten – z.B. die Einschränkungen
IsFile
undIsDirectory
des IIS-Neuschreibungsmoduls. Verwenden Sie in diesem Szenario stattdessen die Middleware.Die Leistung der Middleware stimmt wahrscheinlich nicht mit der Leistung der Module überein.
Benchmarking ist der einzige Weg, um sicher festzustellen, welcher Ansatz die Leistung am meisten beeinträchtigt oder ob die nachlassende Leistung nur geringfügig ist.
Package
Die URL-umschreibende Middleware wird über das Microsoft.AspNetCore.Rewrite-Paket bereitgestellt, das implizit in ASP.NET Core-Apps enthalten ist.
Erweiterung und Optionen
Legen Sie URL-Neuschreibungs- und -Umleitungsregeln fest, indem Sie eine Instanz der RewriteOptions-Klasse erstellen und Erweiterungsmethoden für jede Neuschreibungsregel hinzufügen. Verketten Sie mehrere Regeln in der Reihenfolge miteinander, in der sie verarbeitet werden sollen. Die RewriteOptions
werden an die Middleware zur URL-Neuschreibung übergeben, wenn diese mit UseRewriter zu der Anforderungspipeline hinzugefügt wird:
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}"));
}
Umleitung einer Nicht-WWW-Anforderung an eine WWW-Anforderung
Drei Optionen ermöglichen der App, Nicht-www
-Anforderungen an www
umzuleiten:
AddRedirectToWwwPermanent: Die Anforderung wird dauerhaft an die Unterdomäne
www
umgeleitet, sofern die Anforderung nichtwww
ist. Wird mit dem Statuscode Status308PermanentRedirect umgeleitet.AddRedirectToWww: Die Anforderung wird an die Unterdomäne
www
umgeleitet, sofern die eingehende Anforderung nichtwww
ist. Wird mit dem Statuscode Status307TemporaryRedirect umgeleitet. Eine Überladung ermöglicht es Ihnen, den Statuscode für die Antwort zu senden. Verwenden Sie ein Feld der StatusCodes-Klasse, um einen Statuscode zuzuweisen.
Umleitungs-URL
Verwenden Sie AddRedirect, um Anforderungen umzuleiten. Der erste Parameter enthält Ihren regulären Ausdruck, damit dieser dem Pfad der eingehenden URL zugeordnet werden kann. Beim zweiten Parameter handelt es sich um eine Ersatzzeichenfolge. Der dritte Parameter gibt, falls vorhanden, den Statuscode an. Wenn Sie den Statuscode nicht angeben, wird standardmäßig 302 – Gefunden zurückgegeben, was bedeutet, dass die Ressource kurzzeitig verschoben oder ersetzt wurde.
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}"));
}
Aktivieren Sie in Ihrem Browser die Entwicklertools, und senden Sie eine Anforderung an die Beispiel-App mit dem Pfad /redirect-rule/1234/5678
. Der RegEx stimmt mit dem Anforderungspfad unter redirect-rule/(.*)
überein, und der Pfad wird durch /redirected/1234/5678
ersetzt. Die Umleitungs-URL wird mit dem Statuscode 302 – Gefunden an den Client zurückgesendet. Unter der Umleitungs-URL sendet der Browser eine neue Anforderung, die in dessen Adressleiste angezeigt wird. Da keine Regel in der Beispiel-App mit der Umleitungs-URL übereinstimmt:
- Die zweite Anforderung erhält die Antwort 200 – OK von der App.
- Der Antworttext zeigt die Umleitungs-URL an.
Wenn eine URL weitergeleitet wird, wird ein Roundtrip zum Server ausgelöst.
Warnung
Seien Sie vorsichtig, wenn Sie Umleitungsregeln einrichten. Bei jeder Anforderung an die App werden Umleitungsregeln überprüft – auch nach einer Umleitung. Dabei kann schnell aus Versehen eine Dauerschleife von Umleitungen entstehen.
Ursprüngliche Anforderung: /redirect-rule/1234/5678
Der Teil des Ausdruck in Klammern wird als Erfassungsgruppe bezeichnet. Der Punkt (.
) im Ausdruck steht für Übereinstimmung mit beliebigem Zeichen. Das Sternchen (*
) steht für Übereinstimmung mit dem vorausgehenden Zeichen (keinmal oder mindestens einmal) . Daher werden die letzten beiden Pfadsegmente der URL (1234/5678
) von der Erfassungsgruppe erfasst (.*)
. Alle Werte, die Sie in der Anforderungs-URL nach redirect-rule/
angeben, werden von dieser Erfassungsgruppe erfasst.
Erfassungsgruppen werden in der Ersetzungszeichenfolge mit dem Dollarzeichen ($
) in die Zeichenfolge eingefügt. Danach folgt die Sequenznummer der Erfassung. Der erste Wert der Erfassungsgruppe wird mit $1
abgerufen, der zweite mit $2
. Dies wird in Sequenzen für die Erfassungsgruppen Ihres RegEx weitergeführt. Nur eine Erfassungsgruppe ist in der Beispiel-App im RegEx der Umleitungsregel enthalten. Das bedeutet, dass es in die Ersetzungszeichenfolge nur eine Gruppe eingefügt wird, nämlich $1
. Wenn die Regel angewendet wird, ändert sich die URL in /redirected/1234/5678
.
URL-Umleitung an einen sicheren Endpunkt
Verwenden Sie AddRedirectToHttps, um HTTP-Anforderungen auf denselben Host und Pfad mithilfe des HTTPS-Protokolls umzuleiten. Wenn kein Statuscode angegeben wird, wird für die Middleware standardmäßig 302 – Gefunden zurückgegeben. Wenn kein Port angegeben ist:
- Für die Middleware wird standardmäßig
null
zurückgegeben. - Das Schema ändert sich in
https
(HTTPS-Protokoll), und der Client hat über Port 443 Zugriff auf die Ressource.
Im folgenden Beispiel wird dargestellt, wie Sie den Statuscode 301 - Moved Permanently
festlegen und den Port in 5001 ändern.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Verwenden Sie AddRedirectToHttpsPermanent, um unsichere Anforderungen auf denselben Host und Pfad mit einem sicheren HTTPS-Protokoll auf Port 443 umzuleiten. Die Middleware legt den Statuscode auf 301 - Moved Permanently
fest.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Hinweis
Wenn Sie eine Umleitung an einen sicheren Endpunkt ohne weitere erforderliche Umleitungsregeln durchführen, wird empfohlen, Middleware für HTTPS-Umleitung zu verwenden. Weitere Informationen finden Sie im Artikel zum Erzwingen von HTTPS.
Anhand der Beispiel-App wird veranschaulicht, wie AddRedirectToHttps
oder AddRedirectToHttpsPermanent
verwendet werden sollen. Fügen Sie die Erweiterungsmethode zu den RewriteOptions
hinzu. Senden Sie eine unsichere Anforderung an die App unter einer beliebigen URL. Schließen Sie die Sicherheitswarnung des Browsers, in der Sie darüber informiert werden, dass das selbstsignierte Zertifikat nicht vertrauenswürdig ist, oder erstellen sie eine Ausnahme, um dem Zertifikat zu vertrauen.
Ursprüngliche Anforderung über AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Ursprüngliche Anforderung über AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Umschreiben einer URL
Erstellen Sie mithilfe von AddRewrite eine Regel zum Umschreiben von URLs. Der erste Parameter enthält den RegEx, damit dieser der eingehenden URL zugeordnet werden kann. Beim zweiten Parameter handelt es sich um eine Ersatzzeichenfolge. Der dritte Parameter (skipRemainingRules: {true|false}
) teilt der Middleware mit, ob sie zusätzliche Umschreibungsregeln überspringen soll, wenn die aktuelle Regel angewendet wird.
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}"));
}
Ursprüngliche Anforderung: /rewrite-rule/1234/5678
Das Zirkumflexzeichen (^
) am Anfang des Ausdrucks bedeutet, dass die Übereinstimmung schon am Anfang des URL-Pfads beginnt.
In dem vorherigen Beispiel zu den Umleitungsregeln, redirect-rule/(.*)
, beginnt der RegEx nicht mit einem Zirkumflexzeichen (^
). So kann für eine Übereinstimmung ein beliebiges Zeichen im Pfad vor redirect-rule/
stehen.
Pfad | Match |
---|---|
/redirect-rule/1234/5678 |
Ja |
/my-cool-redirect-rule/1234/5678 |
Ja |
/anotherredirect-rule/1234/5678 |
Ja |
Die Umschreibungsregel (^rewrite-rule/(\d+)/(\d+)
) stimmt nur mit Pfaden überein, wenn sie mit rewrite-rule/
beginnen. Beachten Sie die unterschiedliche Übereinstimmung in der folgenden Tabelle:
Pfad | Match |
---|---|
/rewrite-rule/1234/5678 |
Ja |
/my-cool-rewrite-rule/1234/5678 |
Nr. |
/anotherrewrite-rule/1234/5678 |
Nein |
Auf den ^rewrite-rule/
-Teil des Ausdruck folgen zwei Erfassungsgruppen: (\d+)/(\d+)
. \d
steht für Übereinstimmung mit einer Ziffer (Zahl) . Das Pluszeichen (+
) steht für match one or more of the preceding character (Übereinstimmung mit mindestens einem vorausgehenden Zeichen). Aus diesem Grund muss die URL eine Zahl enthalten, auf die ein Schrägstrich und eine weitere Zahl folgt. Die Erfassungsgruppen werden in die umgeschriebene URL als $1
und $2
eingefügt. Über die Ersetzungszeichenfolge der Neuschreibungsregel werden die Erfassungsgruppen in die Abfragezeichenfolge eingefügt. Der angeforderte /rewrite-rule/1234/5678
-Pfad wird umgeschrieben, um eine Ressource unter /rewritten?var1=1234&var2=5678
abzurufen. Wenn es in der ursprünglichen Anforderung eine Abfragezeichenfolge gibt, bleibt diese erhalten, wenn die URL umgeschrieben wird.
Es gibt keinen Roundtrip zum Server, um die Ressource abzurufen. Wenn es die Ressource gibt, wird sie abgerufen und dem Client mit dem Statuscode 200 – OK zurückgegeben. Da der Client nicht umgeleitet wird, ändert sich die URL in der Adressleiste des Browsers nicht. Clients können nicht erkennen, dass ein Vorgang zum erneuten Schreiben einer URL auf dem Server stattgefunden hat.
Hinweis
Verwenden Sie skipRemainingRules: true
, wo immer das möglich ist, da das Abgleichen von Regeln rechnerisch sehr aufwendig ist und die Antwortzeit der App erhöht. Führen Sie folgende Schritte aus, um die schnellsten App-Antwortzeiten zu erreichen:
- Sortieren Sie Neuschreibungsregeln von der am häufigsten abgeglichenen Regel zu der am seltensten abgeglichenen Regel.
- Überspringen Sie die Verarbeitung der übrigen Regeln, wenn es zu einer Übereinstimmung kommt und keine zusätzlichen Regelverarbeitungen erforderlich sind.
Apache: „mod_rewrite“
Wenden Sie die Apache-Regeln „mod_rewrite“ mit AddApacheModRewrite an. Vergewissern Sie sich, dass die Regeldatei mit der App bereitgestellt wird. Weitere Informationen zu diesen Regeln finden Sie unter Apache: „mod_rewrite“.
Zum Lesen der Regeldatei ApacheModRewrite.txt wird StreamReader verwendet:
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}"));
}
Die Beispiel-App leitet Anforderungen von /apache-mod-rules-redirect/(.\*)
auf /redirected?id=$1
um. Der Antwortstatuscode lautet 302 – Gefunden.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Ursprüngliche Anforderung: /apache-mod-rules-redirect/1234
Die Middleware unterstützt die folgenden Servervariablen für die Apache „mod_rewrite“:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- 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
Regeln zum IIS-Umschreibungsmodul
Um denselben Regelsatz zu verwenden, der für das IIS-Moduls für URL-Neuschreibung gilt, verwenden Sie AddIISUrlRewrite. Vergewissern Sie sich, dass die Regeldatei mit der App bereitgestellt wird. Geben Sie der Middleware nicht die Anweisung, die web.config-Datei der App zu verwenden, wenn sie auf der Windows Server-IIS ausgeführt wird. Bei IIS sollten diese Regeln außerhalb der web.config-Datei der App gespeichert werden, um Konflikte mit dem IIS-Neuschreibungsmodul zu vermeiden. Weitere Informationen und Beispiele zu den Regeln zum IIS-Umschreibungsmodul finden Sie unter Using Url Rewrite Module 2.0 (Verwenden des URL-Umschreibungsmoduls 2.0) und URL Rewrite Module Configuration Reference (Konfigurationsreferenz des URL-Umschreibungsmoduls).
Zum Lesen der Regeldatei IISUrlRewrite.xml
wird StreamReader verwendet:
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}"));
}
Die Beispiel-App schreibt Anforderungen von /iis-rules-rewrite/(.*)
in /rewritten?id=$1
um. Die Antwort wird an den Client mit dem Statuscode 200 – OK gesendet.
<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>
Ursprüngliche Anforderung: /iis-rules-rewrite/1234
Wenn Sie über ein aktives IIS-Umschreibungsmodul verfügen, für das die Regeln auf Serverebene konfiguriert sind, die negative Auswirkungen auf Ihre App hätten, können Sie das IIS-Umschreibungsmodul für die App deaktivieren. Weitere Informationen finden Sie unter Disabling IIS modules (Deaktivieren von IIS-Modulen).
Nicht unterstützte Features
Die Middleware unterstützt die folgenden Features des IIS-URL-Umschreibungsmoduls nicht:
- Ausgehende Regeln
- Benutzerdefinierte Servervariablen
- Platzhalter
- LogRewrittenUrl
Unterstützte Servervariablen
Die Middleware unterstützt die folgenden Servervariablen für das IIS-URL-Umschreibungsmodul:
- 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
Hinweis
Sie können IFileProvider auch über PhysicalFileProvider abrufen. Über diesen Ansatz können Sie flexibler einen Speicherort für die Dateien der Umschreibungsregeln auswählen. Vergewissern Sie sich, dass die Dateien zu den Umschreibungsregeln auf dem Server unter dem von Ihnen angegebenen Pfad bereitgestellt werden.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Methodenbasierte Regel
Verwenden Sie Add, um Ihre eigene Regellogik in einer Methode zu implementieren. Add
macht RewriteContext verfügbar, wodurch die Verwendung von HttpContext in Ihrer Methode ermöglicht wird. RewriteContext.Result bestimmt, wie die zusätzliche Pipelineverarbeitung erfolgt. Legen Sie den Wert auf eines der RuleResult-Felder fest, die in der folgenden Tabelle beschrieben sind:
Umschreiben von Kontext – Ergebnisse | Aktion |
---|---|
RuleResult.ContinueRules (Standardwert) |
Regeln weiter anwenden. |
RuleResult.EndResponse |
Regeln nicht mehr anwenden und Antwort senden. |
RuleResult.SkipRemainingRules |
Regeln nicht mehr anwenden, und den Kontext an die nächste Middleware senden. |
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}"));
}
In der Beispiel-App wird eine Methode dargestellt, die Anforderungen für Pfade weiterleitet, die auf .xml
enden. Wenn eine Anforderung für /file.xml
erfolgt, wird sie zu /xmlfiles/file.xml
umgeleitet. Der Statuscode wird auf 301 - Moved Permanently
festgelegt. Wenn vom Browser eine neue Anforderung für /xmlfiles/file.xml
gesendet wird, wird dem Client die Datei von Middleware für statische Dateien aus dem Ordner wwwroot/xmlfiles bereitgestellt. Legen Sie für eine Umleitung den Statuscode der Antwort explizit fest. Andernfalls wird ein Statuscode 200 – OK zurückgegeben, und die Umleitung findet nicht auf dem Client statt.
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;
}
}
Bei diesem Ansatz können auch Anforderungen erneut generiert werden. In der Beispiel-App wird demonstriert, wie der Pfad für eine beliebige Textdateianforderung umgeschrieben wird, um die Textdatei file.txt aus dem Ordner wwwroot bereitzustellen. Middleware für statische Dateien stellt die Datei bereit, die auf dem aktualisierten Anforderungspfad basiert:
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";
}
}
IRule-basierte Regel
Um Regellogik in einer Klasse zu nutzen, die die IRule-Schnittstelle implementiert, verwenden Sie Add. Wenn Sie IRule
verwenden, können Sie flexibler entscheiden, ob Sie eine methodenbasierte Regel verwenden möchten. Ihre Implementierungsklasse kann einen Konstruktor enthalten, wodurch Sie Parameter für die ApplyRule-Methode übergeben können.
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}"));
}
Die Werte für die Parameter in der Beispiel-App für extension
und newPath
werden auf verschiedene Bedingungen geprüft. extension
muss einen Wert enthalten, der .png
, .jpg
oder .gif entspricht. Wenn newPath
nicht gültig ist, wird ArgumentException nicht ausgelöst. Wenn eine Anforderung für image.png
erfolgt, wird sie zu /png-images/image.png
umgeleitet. Wenn eine Anforderung für image.jpg
erfolgt, wird sie zu /jpg-images/image.jpg
umgeleitet. Der Statuscode wird auf 301 - Moved Permanently
festgelegt, und context.Result
erhält die Anweisung, Verarbeitungsregeln zu beenden und die Antwort zu senden.
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;
}
}
}
Ursprüngliche Anforderung: /image.png
Ursprüngliche Anforderung: /image.jpg
RegEx-Beispiele
Ziel | RegEx-Zeichenfolge und übereinstimmendes Beispiel |
Ersetzungszeichenfolge und Ausgabebeispiel |
---|---|---|
Umschreiben des Pfads in die Abfragezeichenfolge | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Entfernen des nachgestellten Schrägstrichs | (.*)/$ /path/ |
$1 /path |
Erzwingen des nachgestellten Schrägstrichs | (.*[^/])$ /path |
$1/ /path/ |
Vermeiden des Umschreibens von bestimmten Anforderungen | ^(.*)(?<!\.axd)$ oder ^(?!.*\.axd$)(.*)$ Ja: /resource.htm Nein: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Ändern der Anordnung von URL-Segmenten | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Ersetzen von URL-Segmenten | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
In diesem Artikel wird das Umschreiben von URLs beschrieben. Außerdem erhalten Sie Anweisungen zur Verwendung der URL-umschreibenden Middleware in ASP.NET Core-Apps.
Bei der URL-Umschreibung werden die Anforderungs-URLs verändert, die auf mindesten einer vordefinierten Regel basieren. Es wird eine Abstraktion zwischen den Speicherorten und Adressen von Ressourcen erstellt, sodass diese nicht eng miteinander verknüpft sind. Die URL-Neuschreibung ist hilfreich in verschiedenen Szenarios wie:
- Kurzzeitiges oder permanentes Verschieben oder Ersetzen von Serverressourcen, sowie Erhalten von stabilen Locators für diese Ressourcen.
- Verteilen der Verarbeitung von Anforderungen auf verschiedene Apps oder Bereiche einer App.
- Entfernen, Hinzufügen oder Umorganisieren von URL-Segmenten bei eingehenden Anforderungen.
- Optimieren von öffentlichen URLs für die Suchmaschinenoptimierung (Search Engine Optimization, SEO).
- Gestatten der Verwendung von angezeigten öffentlichen URLs, um Besuchern zu helfen, den Inhalt vorherzusagen, der durch die Anforderung einer Ressource zurückgegeben wird.
- Umleiten von unsicheren Anforderungen auf sichere Endpunkte.
- Verhindern von Hotlinks zu externen Websites, die eine gehostete statische Ressource auf einer anderen Website verwenden, bei der die Ressource zu ihrem eigenen Inhalt verlinkt wird.
Hinweis
Wenn Sie URLs umschreiben, kann das negative Auswirkungen auf die Leistung einer App haben. Wenn möglich, sollten Sie so wenig Regeln wie möglich erstellen und darauf achten, dass diese nicht zu kompliziert sind.
Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
Umleiten und Umschreiben von URLs
Der Unterschied zwischen dem Umleiten und Neu schreiben von URLs ist zwar gering, allerdings haben die beiden Verfahren sehr unterschiedliche Auswirkungen auf die Bereitstellung von Ressourcen für Clients. Die URL-umschreibenden Middleware von ASP.NET Core kann für beide Vorgänge verwendet werden.
Bei der Umleitung von URLs findet ein clientseitiger Vorgang statt, bei dem der Client angewiesen wird, auf eine Ressource unter einer anderen Adresse zuzugreifen, als die, die der Client ursprünglich angefordert hat. Dafür ist ein Roundtrip zum Server erforderlich. Die Umleitungs-URL, die an den Client zurückgegeben wird, wird in der Adressleiste des Browsers angezeigt, wenn der Client eine neue Anforderung an die Ressource sendet.
Wenn /resource
auf /different-resource
umgeleitet wird, sendet der Server die Antwort, dass der Client die Ressource unter /different-resource
abrufen soll. In der Antwort ist außerdem ein Statuscode enthalten, aus dem entnommen werden kann, ob die Umleitung temporär oder permanent ist.
Wenn Anforderungen auf eine andere URL umgeleitet werden, muss angegeben werden, ob die Umleitung temporär oder permanent sein soll. Geben Sie hierzu den Statuscode mit der Antwort an:
Der Statuscode
301 - Moved Permanently
wird verwendet, wenn der Ressource eine neue permanente URL zugewiesen wurde, und Sie dem Client die Anweisung geben möchten, dass alle zukünftigen Anforderungen an die Ressource die neue URL verwenden sollen. Der Client kann die Antwort zwischenspeichern und wiederverwenden, wenn der Statuscode 301 empfangen wird.Der Statuscode 302 – Gefunden wird verwendet, wenn die Umleitung temporär ist oder sowieso Änderungen vorbehalten sind. Der Statuscode 302 teilt dem Client mit, dass die URL nicht gespeichert und nicht wiederverwendet werden soll.
Weitere Informationen zu Statuscodes finden Sie unter RFC 9110: Statuscodedefinitionen.
Bei der Neuschreibung einer URL handelt es sich um einen serverseitigen Vorgang, bei dem eine Ressource von einer anderen Ressourcenadresse, als der vom Client angeforderten, bereitgestellt wird. Wenn eine URL neu geschrieben wird, ist kein Roundtrip zum Server erforderlich. Die neu geschriebene URL wird nicht an den Server zurückgegeben und nicht in der Adressleiste des Browsers angezeigt.
Wenn /resource
in /different-resource
umgeschrieben wird, ruft der Server die Ressource intern ab und gibt sie zurück an /different-resource
.
Auch wenn der Client die Ressource unter der neu geschriebene URL abrufen kann, erhält er nicht die Information, dass die Ressource unter der umgeschriebenen URL gespeichert ist, wenn er die Anforderung sendet und eine Antwort erhält.
URL-umschreibende Beispiel-App
Mit der Beispiel-App können Sie die Features der Middleware zur URL-Neuschreibung testen. Die App wendet Umleitungs- und Neuschreibungsregeln an und zeigt die umgeleitete oder neu geschriebene URL für verschiedene Szenarios an.
Empfohlene Verwendung der URL-umschreibenden Middleware
Sie können Middleware zur URL-Neuschreibung verwenden, wenn die folgenden Ansätze nicht möglich sind:
- URL Rewrite module with IIS on Windows Server (URL-Neuschreibungsmodul mit IIS auf Windows-Server)
- Apache mod_rewrite module on Apache Server (Apache mod_rewrite-Modul auf Apache-Server)
- URL rewriting on Nginx (URL-Neuschreibung auf Nginx)
Sie können die Middleware auch verwenden, wenn die App auf dem HTTP.sys-Server (früher als WebListener bezeichnet) gehostet wird.
Die Hauptgründe für die Verwendung der serverbasierten Technologien zur URL-Neuschreibung in IIS, Apache und Nginx sind:
Die Middleware unterstützt nicht alle Features dieser Module.
Einige Features der Servermodule funktionieren nicht mit ASP.NET Core-Projekten – z.B. die Einschränkungen
IsFile
undIsDirectory
des IIS-Neuschreibungsmoduls. Verwenden Sie in diesem Szenario stattdessen die Middleware.Die Leistung der Middleware stimmt wahrscheinlich nicht mit der Leistung der Module überein.
Benchmarking ist der einzige Weg, um sicher festzustellen, welcher Ansatz die Leistung am meisten beeinträchtigt oder ob die nachlassende Leistung nur geringfügig ist.
Package
Um die Middleware in Ihr Projekt einzuschließen, fügen Sie einen Paketverweis zum Microsoft.AspNetCore.App-Metapaket in der Projektdatei ein, die das Microsoft.AspNetCore.Rewrite-Paket enthält.
Wenn Sie das Microsoft.AspNetCore.App
Metapaket nicht verwenden, fügen Sie dem Paket einen Projekthinweis hinzuMicrosoft.AspNetCore.Rewrite
.
Erweiterung und Optionen
Legen Sie URL-Neuschreibungs- und -Umleitungsregeln fest, indem Sie eine Instanz der RewriteOptions-Klasse erstellen und Erweiterungsmethoden für jede Neuschreibungsregel hinzufügen. Verketten Sie mehrere Regeln in der Reihenfolge miteinander, in der sie verarbeitet werden sollen. Die RewriteOptions
werden an die Middleware zur URL-Neuschreibung übergeben, wenn diese mit UseRewriter zu der Anforderungspipeline hinzugefügt wird:
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}"));
}
Umleitung einer Nicht-WWW-Anforderung an eine WWW-Anforderung
Drei Optionen ermöglichen der App, Nicht-www
-Anforderungen an www
umzuleiten:
AddRedirectToWwwPermanent: Die Anforderung wird dauerhaft an die Unterdomäne
www
umgeleitet, sofern die Anforderung nichtwww
ist. Wird mit dem Statuscode Status308PermanentRedirect umgeleitet.AddRedirectToWww: Die Anforderung wird an die Unterdomäne
www
umgeleitet, sofern die eingehende Anforderung nichtwww
ist. Wird mit dem Statuscode Status307TemporaryRedirect umgeleitet. Eine Überladung ermöglicht es Ihnen, den Statuscode für die Antwort zu senden. Verwenden Sie ein Feld der StatusCodes-Klasse, um einen Statuscode zuzuweisen.
Umleitungs-URL
Verwenden Sie AddRedirect, um Anforderungen umzuleiten. Der erste Parameter enthält Ihren RegEx, damit dieser dem Pfad der eingehenden URL zugeordnet werden kann. Beim zweiten Parameter handelt es sich um eine Ersatzzeichenfolge. Der dritte Parameter gibt, falls vorhanden, den Statuscode an. Wenn Sie den Statuscode nicht angeben, wird standardmäßig 302 – Gefunden zurückgegeben, was bedeutet, dass die Ressource kurzzeitig verschoben oder ersetzt wurde.
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}"));
}
Aktivieren Sie in Ihrem Browser die Entwicklertools, und senden Sie eine Anforderung an die Beispiel-App mit dem Pfad /redirect-rule/1234/5678
. Der RegEx stimmt mit dem Anforderungspfad unter redirect-rule/(.*)
überein, und der Pfad wird durch /redirected/1234/5678
ersetzt. Die Umleitungs-URL wird mit dem Statuscode 302 – Gefunden an den Client zurückgesendet. Unter der Umleitungs-URL sendet der Browser eine neue Anforderung, die in dessen Adressleiste angezeigt wird. Da keine Regel in der Beispiel-App mit der Umleitungs-URL übereinstimmt:
- Die zweite Anforderung erhält die Antwort 200 – OK von der App.
- Der Antworttext zeigt die Umleitungs-URL an.
Wenn eine URL weitergeleitet wird, wird ein Roundtrip zum Server ausgelöst.
Warnung
Seien Sie vorsichtig, wenn Sie Umleitungsregeln einrichten. Bei jeder Anforderung an die App werden Umleitungsregeln überprüft – auch nach einer Umleitung. Dabei kann schnell aus Versehen eine Dauerschleife von Umleitungen entstehen.
Ursprüngliche Anforderung: /redirect-rule/1234/5678
Der Teil des Ausdruck in Klammern wird als Erfassungsgruppe bezeichnet. Der Punkt (.
) im Ausdruck steht für Übereinstimmung mit beliebigem Zeichen. Das Sternchen (*
) steht für Übereinstimmung mit dem vorausgehenden Zeichen (keinmal oder mindestens einmal) . Daher werden die letzten beiden Pfadsegmente der URL (1234/5678
) von der Erfassungsgruppe erfasst (.*)
. Alle Werte, die Sie in der Anforderungs-URL nach redirect-rule/
angeben, werden von dieser Erfassungsgruppe erfasst.
Erfassungsgruppen werden in der Ersetzungszeichenfolge mit dem Dollarzeichen ($
) in die Zeichenfolge eingefügt. Danach folgt die Sequenznummer der Erfassung. Der erste Wert der Erfassungsgruppe wird mit $1
abgerufen, der zweite mit $2
. Dies wird in Sequenzen für die Erfassungsgruppen Ihres RegEx weitergeführt. Nur eine Erfassungsgruppe ist in der Beispiel-App im RegEx der Umleitungsregel enthalten. Das bedeutet, dass es in die Ersetzungszeichenfolge nur eine Gruppe eingefügt wird, nämlich $1
. Wenn die Regel angewendet wird, ändert sich die URL in /redirected/1234/5678
.
URL-Umleitung an einen sicheren Endpunkt
Verwenden Sie AddRedirectToHttps, um HTTP-Anforderungen auf denselben Host und Pfad mithilfe des HTTPS-Protokolls umzuleiten. Wenn kein Statuscode angegeben wird, wird für die Middleware standardmäßig 302 – Gefunden zurückgegeben. Wenn kein Port angegeben ist:
- Für die Middleware wird standardmäßig
null
zurückgegeben. - Das Schema ändert sich in
https
(HTTPS-Protokoll), und der Client hat über Port 443 Zugriff auf die Ressource.
Im folgenden Beispiel wird dargestellt, wie Sie den Statuscode 301 - Moved Permanently
festlegen und den Port in 5001 ändern.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttps(301, 5001);
app.UseRewriter(options);
}
Verwenden Sie AddRedirectToHttpsPermanent, um unsichere Anforderungen auf denselben Host und Pfad mit einem sicheren HTTPS-Protokoll auf Port 443 umzuleiten. Die Middleware legt den Statuscode auf 301 - Moved Permanently
fest.
public void Configure(IApplicationBuilder app)
{
var options = new RewriteOptions()
.AddRedirectToHttpsPermanent();
app.UseRewriter(options);
}
Hinweis
Wenn Sie eine Umleitung an einen sicheren Endpunkt ohne weitere erforderliche Umleitungsregeln durchführen, wird empfohlen, Middleware für HTTPS-Umleitung zu verwenden. Weitere Informationen finden Sie im Artikel zum Erzwingen von HTTPS.
Anhand der Beispiel-App wird veranschaulicht, wie AddRedirectToHttps
oder AddRedirectToHttpsPermanent
verwendet werden sollen. Fügen Sie die Erweiterungsmethode zu den RewriteOptions
hinzu. Senden Sie eine unsichere Anforderung an die App unter einer beliebigen URL. Schließen Sie die Sicherheitswarnung des Browsers, in der Sie darüber informiert werden, dass das selbstsignierte Zertifikat nicht vertrauenswürdig ist, oder erstellen sie eine Ausnahme, um dem Zertifikat zu vertrauen.
Ursprüngliche Anforderung über AddRedirectToHttps(301, 5001)
: http://localhost:5000/secure
Ursprüngliche Anforderung über AddRedirectToHttpsPermanent
: http://localhost:5000/secure
Umschreiben einer URL
Erstellen Sie mithilfe von AddRewrite eine Regel zum Umschreiben von URLs. Der erste Parameter enthält den RegEx, damit dieser der eingehenden URL zugeordnet werden kann. Beim zweiten Parameter handelt es sich um eine Ersatzzeichenfolge. Der dritte Parameter (skipRemainingRules: {true|false}
) teilt der Middleware mit, ob sie zusätzliche Umschreibungsregeln überspringen soll, wenn die aktuelle Regel angewendet wird.
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}"));
}
Ursprüngliche Anforderung: /rewrite-rule/1234/5678
Das Zirkumflexzeichen (^
) am Anfang des Ausdrucks bedeutet, dass die Übereinstimmung schon am Anfang des URL-Pfads beginnt.
In dem vorherigen Beispiel zu den Umleitungsregeln, redirect-rule/(.*)
, beginnt der RegEx nicht mit einem Zirkumflexzeichen (^
). So kann für eine Übereinstimmung ein beliebiges Zeichen im Pfad vor redirect-rule/
stehen.
Pfad | Match |
---|---|
/redirect-rule/1234/5678 |
Ja |
/my-cool-redirect-rule/1234/5678 |
Ja |
/anotherredirect-rule/1234/5678 |
Ja |
Die Umschreibungsregel (^rewrite-rule/(\d+)/(\d+)
) stimmt nur mit Pfaden überein, wenn sie mit rewrite-rule/
beginnen. Beachten Sie die unterschiedliche Übereinstimmung in der folgenden Tabelle:
Pfad | Match |
---|---|
/rewrite-rule/1234/5678 |
Ja |
/my-cool-rewrite-rule/1234/5678 |
Nr. |
/anotherrewrite-rule/1234/5678 |
Nein |
Auf den ^rewrite-rule/
-Teil des Ausdruck folgen zwei Erfassungsgruppen: (\d+)/(\d+)
. \d
steht für Übereinstimmung mit einer Ziffer (Zahl) . Das Pluszeichen (+
) steht für match one or more of the preceding character (Übereinstimmung mit mindestens einem vorausgehenden Zeichen). Aus diesem Grund muss die URL eine Zahl enthalten, auf die ein Schrägstrich und eine weitere Zahl folgt. Die Erfassungsgruppen werden in die umgeschriebene URL als $1
und $2
eingefügt. Über die Ersetzungszeichenfolge der Neuschreibungsregel werden die Erfassungsgruppen in die Abfragezeichenfolge eingefügt. Der angeforderte /rewrite-rule/1234/5678
-Pfad wird umgeschrieben, um eine Ressource unter /rewritten?var1=1234&var2=5678
abzurufen. Wenn es in der ursprünglichen Anforderung eine Abfragezeichenfolge gibt, bleibt diese erhalten, wenn die URL umgeschrieben wird.
Es gibt keinen Roundtrip zum Server, um die Ressource abzurufen. Wenn es die Ressource gibt, wird sie abgerufen und dem Client mit dem Statuscode 200 – OK zurückgegeben. Da der Client nicht umgeleitet wird, ändert sich die URL in der Adressleiste des Browsers nicht. Clients können nicht erkennen, dass ein Vorgang zum erneuten Schreiben einer URL auf dem Server stattgefunden hat.
Hinweis
Verwenden Sie skipRemainingRules: true
, wo immer das möglich ist, da das Abgleichen von Regeln rechnerisch sehr aufwendig ist und die Antwortzeit der App erhöht. Führen Sie folgende Schritte aus, um die schnellsten App-Antwortzeiten zu erreichen:
- Sortieren Sie Neuschreibungsregeln von der am häufigsten abgeglichenen Regel zu der am seltensten abgeglichenen Regel.
- Überspringen Sie die Verarbeitung der übrigen Regeln, wenn es zu einer Übereinstimmung kommt und keine zusätzlichen Regelverarbeitungen erforderlich sind.
Apache: „mod_rewrite“
Wenden Sie die Apache-Regeln „mod_rewrite“ mit AddApacheModRewrite an. Vergewissern Sie sich, dass die Regeldatei mit der App bereitgestellt wird. Weitere Informationen zu diesen Regeln finden Sie unter Apache: „mod_rewrite“.
Zum Lesen der Regeldatei ApacheModRewrite.txt wird StreamReader verwendet:
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}"));
}
Die Beispiel-App leitet Anforderungen von /apache-mod-rules-redirect/(.\*)
auf /redirected?id=$1
um. Der Antwortstatuscode lautet 302 – Gefunden.
# Rewrite path with additional sub directory
RewriteRule ^/apache-mod-rules-redirect/(.*) /redirected?id=$1 [L,R=302]
Ursprüngliche Anforderung: /apache-mod-rules-redirect/1234
Die Middleware unterstützt die folgenden Servervariablen für die Apache „mod_rewrite“:
- CONN_REMOTE_ADDR
- HTTP_ACCEPT
- HTTP_CONNECTION
- HTTP_COOKIE
- HTTP_FORWARDED
- HTTP_HOST
- HTTP_REFERER
- HTTP_USER_AGENT
- HTTPS
- 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
Regeln zum IIS-Umschreibungsmodul
Um denselben Regelsatz zu verwenden, der für das IIS-Moduls für URL-Neuschreibung gilt, verwenden Sie AddIISUrlRewrite. Vergewissern Sie sich, dass die Regeldatei mit der App bereitgestellt wird. Geben Sie der Middleware nicht die Anweisung, die web.config-Datei der App zu verwenden, wenn sie auf der Windows Server-IIS ausgeführt wird. Bei IIS sollten diese Regeln außerhalb der web.config-Datei der App gespeichert werden, um Konflikte mit dem IIS-Neuschreibungsmodul zu vermeiden. Weitere Informationen und Beispiele zu den Regeln zum IIS-Umschreibungsmodul finden Sie unter Using Url Rewrite Module 2.0 (Verwenden des URL-Umschreibungsmoduls 2.0) und URL Rewrite Module Configuration Reference (Konfigurationsreferenz des URL-Umschreibungsmoduls).
Zum Lesen der Regeldatei IISUrlRewrite.xml
wird StreamReader verwendet:
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}"));
}
Die Beispiel-App schreibt Anforderungen von /iis-rules-rewrite/(.*)
in /rewritten?id=$1
um. Die Antwort wird an den Client mit dem Statuscode 200 – OK gesendet.
<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>
Ursprüngliche Anforderung: /iis-rules-rewrite/1234
Wenn Sie über ein aktives IIS-Umschreibungsmodul verfügen, für das die Regeln auf Serverebene konfiguriert sind, die negative Auswirkungen auf Ihre App hätten, können Sie das IIS-Umschreibungsmodul für die App deaktivieren. Weitere Informationen finden Sie unter Disabling IIS modules (Deaktivieren von IIS-Modulen).
Nicht unterstützte Features
Die im Lieferumfang von ASP.NET Core 2.x enthaltene Middleware unterstützt die folgenden Features des IIS-URL-Umschreibungsmoduls nicht:
- Ausgehende Regeln
- Benutzerdefinierte Servervariablen
- Platzhalter
- LogRewrittenUrl
Unterstützte Servervariablen
Die Middleware unterstützt die folgenden Servervariablen für das IIS-URL-Umschreibungsmodul:
- 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
Hinweis
Sie können IFileProvider auch über PhysicalFileProvider abrufen. Über diesen Ansatz können Sie flexibler einen Speicherort für die Dateien der Umschreibungsregeln auswählen. Vergewissern Sie sich, dass die Dateien zu den Umschreibungsregeln auf dem Server unter dem von Ihnen angegebenen Pfad bereitgestellt werden.
PhysicalFileProvider fileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory());
Methodenbasierte Regel
Verwenden Sie Add, um Ihre eigene Regellogik in einer Methode zu implementieren. Add
macht RewriteContext verfügbar, wodurch die Verwendung von HttpContext in Ihrer Methode ermöglicht wird. RewriteContext.Result bestimmt, wie die zusätzliche Pipelineverarbeitung erfolgt. Legen Sie den Wert auf eines der RuleResult-Felder fest, die in der folgenden Tabelle beschrieben sind:
Umschreiben von Kontext – Ergebnisse | Aktion |
---|---|
RuleResult.ContinueRules (Standardwert) |
Regeln weiter anwenden. |
RuleResult.EndResponse |
Regeln nicht mehr anwenden und Antwort senden. |
RuleResult.SkipRemainingRules |
Regeln nicht mehr anwenden, und den Kontext an die nächste Middleware senden. |
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}"));
}
In der Beispiel-App wird eine Methode dargestellt, die Anforderungen für Pfade weiterleitet, die auf .xml
enden. Wenn eine Anforderung für /file.xml
erfolgt, wird sie zu /xmlfiles/file.xml
umgeleitet. Der Statuscode wird auf 301 - Moved Permanently
festgelegt. Wenn vom Browser eine neue Anforderung für /xmlfiles/file.xml
gesendet wird, wird dem Client die Datei von Middleware für statische Dateien aus dem Ordner wwwroot/xmlfiles bereitgestellt. Legen Sie für eine Umleitung den Statuscode der Antwort explizit fest. Andernfalls wird ein Statuscode 200 – OK zurückgegeben, und die Umleitung findet nicht auf dem Client statt.
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;
}
}
Bei diesem Ansatz können auch Anforderungen erneut generiert werden. In der Beispiel-App wird demonstriert, wie der Pfad für eine beliebige Textdateianforderung umgeschrieben wird, um die Textdatei file.txt aus dem Ordner wwwroot bereitzustellen. Middleware für statische Dateien stellt die Datei bereit, die auf dem aktualisierten Anforderungspfad basiert:
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";
}
}
IRule-basierte Regel
Um Regellogik in einer Klasse zu nutzen, die die IRule-Schnittstelle implementiert, verwenden Sie Add. Wenn Sie IRule
verwenden, können Sie flexibler entscheiden, ob Sie eine methodenbasierte Regel verwenden möchten. Ihre Implementierungsklasse kann einen Konstruktor enthalten, wodurch Sie Parameter für die ApplyRule-Methode übergeben können.
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}"));
}
Die Werte für die Parameter in der Beispiel-App für extension
und newPath
werden auf verschiedene Bedingungen geprüft. extension
muss einen Wert enthalten, der .png
, .jpg
oder .gif entspricht. Wenn newPath
nicht gültig ist, wird ArgumentException nicht ausgelöst. Wenn eine Anforderung für image.png
erfolgt, wird sie zu /png-images/image.png
umgeleitet. Wenn eine Anforderung für image.jpg
erfolgt, wird sie zu /jpg-images/image.jpg
umgeleitet. Der Statuscode wird auf 301 - Moved Permanently
festgelegt, und context.Result
erhält die Anweisung, Verarbeitungsregeln zu beenden und die Antwort zu senden.
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;
}
}
}
Ursprüngliche Anforderung: /image.png
Ursprüngliche Anforderung: /image.jpg
RegEx-Beispiele
Ziel | RegEx-Zeichenfolge und übereinstimmendes Beispiel |
Ersetzungszeichenfolge und Ausgabebeispiel |
---|---|---|
Umschreiben des Pfads in die Abfragezeichenfolge | ^path/(.*)/(.*) /path/abc/123 |
path?var1=$1&var2=$2 /path?var1=abc&var2=123 |
Entfernen des nachgestellten Schrägstrichs | (.*)/$ /path/ |
$1 /path |
Erzwingen des nachgestellten Schrägstrichs | (.*[^/])$ /path |
$1/ /path/ |
Vermeiden des Umschreibens von bestimmten Anforderungen | ^(.*)(?<!\.axd)$ oder ^(?!.*\.axd$)(.*)$ Ja: /resource.htm Nein: /resource.axd |
rewritten/$1 /rewritten/resource.htm /resource.axd |
Ändern der Anordnung von URL-Segmenten | path/(.*)/(.*)/(.*) path/1/2/3 |
path/$3/$2/$1 path/3/2/1 |
Ersetzen von URL-Segmenten | ^(.*)/segment2/(.*) /segment1/segment2/segment3 |
$1/replaced/$2 /segment1/replaced/segment3 |
Zusätzliche Ressourcen
- Anzeigen oder Herunterladen von Beispielcode (Vorgehensweise zum Herunterladen)
- RewriteMiddleware-Quelle auf GitHub
- Anwendungsstart in ASP.NET Core
- ASP.NET Core-Middleware
- Reguläre Ausdrücke in .NET
- Sprachelemente für reguläre Ausdrücke – Kurzübersicht
- Apache: „mod_rewrite“
- Using Url Rewrite Module 2.0 (for IIS) (Verwenden des URL-Umschreibungsmoduls 2.0 (für IIS))
- URL Rewrite Module Configuration Reference (Konfigurationsreferenz für das URL-Umschreibungsmodul)
- Einfache Strukturierung von URLs
- 10 URL Rewriting Tips and Tricks (10 Tipps zum Umschreiben von URL)
- To slash or not to slash (Schrägstriche setzen oder nicht setzen)