Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier les répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer de répertoire.
Note
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 10 de cet article.
Warning
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.
La journalisation HTTP est un intergiciel qui journalise des informations sur les requêtes HTTP entrantes et les réponses HTTP. La journalisation HTTP fournit les logs suivants :
- Informations sur les requêtes HTTP
- Propriétés communes
- Headers
- Body
- Informations de réponse HTTP
La journalisation HTTP peut :
- Journaliser toutes les requêtes et les réponses ou uniquement les requêtes et réponses qui répondent à certains critères.
- Sélectionner les parties de la requête et de la réponse qui sont journalisées.
- Vous autoriser à rédiger des informations sensibles à partir des journaux d’activité.
La journalisation HTTP peut réduire les performances d’une application, en particulier lors de la journalisation des corps de requête et de réponse. Tenez compte de l’impact sur les performances lorsque vous sélectionnez les champs à journaliser. Testez l’impact des propriétés de journalisation sélectionnées sur les performances.
Warning
La journalisation HTTP peut potentiellement journaliser des informations d’identification personnelle. Tenez compte des risques, et évitez de journaliser des informations sensibles. Pour plus d’informations sur la rédaction des données sensibles, consultez la rédaction des données sensibles
Activer la journalisation HTTP
La journalisation HTTP est activée en appelant AddHttpLogging et UseHttpLogging, comme illustré dans l’exemple suivant :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Hello World!");
app.Run();
L’expression lambda vide dans l’exemple précédent d’appel de AddHttpLogging ajoute l’intergiciel avec la configuration par défaut. Par défaut, la journalisation HTTP journalise les propriétés courantes telles que le chemin d’accès, le code d’état et les en-têtes des requêtes et des réponses.
Ajoutez la ligne suivante au fichier appsettings.Development.json au niveau "LogLevel": { afin que les logs HTTP soient affichés :
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Avec la configuration par défaut, une requête et une réponse sont enregistrées sous la forme d’une paire de messages similaire à l’exemple suivant :
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
Request:
Protocol: HTTP/2
Method: GET
Scheme: https
PathBase:
Path: /
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Host: localhost:52941
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.61
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: [Redacted]
sec-ch-ua: [Redacted]
sec-ch-ua-mobile: [Redacted]
sec-ch-ua-platform: [Redacted]
sec-fetch-site: [Redacted]
sec-fetch-mode: [Redacted]
sec-fetch-user: [Redacted]
sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
StatusCode: 200
Content-Type: text/plain; charset=utf-8
Date: Tue, 24 Oct 2023 02:03:53 GMT
Server: Kestrel
Options de journalisation HTTP
Pour configurer des options globales pour l’intergiciel de journalisation HTTP, appelez-AddHttpLogging dans Program.csà l’aide de l’expression lambda pour configurer HttpLoggingOptions.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Note
Dans l’exemple précédent et les exemples suivants, UseHttpLogging sont appelés après UseStaticFiles. La journalisation HTTP n’est donc pas activée pour les fichiers statiques. Pour activer la journalisation HTTP de fichier statique, appelez UseHttpLogging avant UseStaticFiles.
LoggingFields
HttpLoggingOptions.LoggingFields est un indicateur d’énumération qui configure certaines parties de la requête et de la réponse à journaliser.
LoggingFields a la valeur par défaut RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders et ResponseHeaders
RequestHeaders et ResponseHeaders sont des ensembles d’en-têtes HTTP journalisés. Les valeurs d’en-tête sont journalisées uniquement pour les noms d’en-tête qui se trouvent dans ces collections. Le code suivant ajoute sec-ch-ua à RequestHeaders, de sorte que la valeur de l’en-tête sec-ch-ua est journalisée. Et il ajoute MyResponseHeader à ResponseHeaders, de sorte que la valeur de l’en-tête MyResponseHeader est journalisée. Si ces lignes sont supprimées, les valeurs de ces en-têtes sont [Redacted].
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
MediaTypeOptions
MediaTypeOptions fournit la configuration permettant de sélectionner l’encodage à utiliser pour un type de média spécifique.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Cette approche peut également être utilisée pour activer la journalisation des données qui ne sont pas journalisées par défaut (par exemple, les données de formulaire, qui peuvent avoir un type de média tel que application/x-www-form-urlencoded ou multipart/form-data).
Méthodes MediaTypeOptions
RequestBodyLogLimit et ResponseBodyLogLimit
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
CombineLogs
Définir CombineLogs sur true configure l’intergiciel pour consolider tous ses journaux activés pour chaque requête et sa réponse correspondante en un seul journal à la fin. Cela inclut la requête, le corps de la requête, la réponse, le corps de la réponse et la durée.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Configuration spécifique au point de terminaison
Pour une configuration spécifique au point de terminaison dans des applications API minimales, une méthode d’extension WithHttpLogging est disponible. L’exemple suivant montre comment configurer la journalisation HTTP pour un point de terminaison :
app.MapGet("/response", () => "Hello World! (logging response)")
.WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);
Pour la configuration spécifique au point de terminaison dans les applications qui utilisent des contrôleurs, l’attribut[HttpLogging] est disponible. L’attribut peut également être utilisé dans des applications API minimales, comme illustré dans l’exemple suivant :
app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
() => "Hello World! (logging duration)");
IHttpLoggingInterceptor
IHttpLoggingInterceptor est l’interface d’un service qui peut être implémenté pour gérer les rappels par requête et par réponse pour personnaliser les détails enregistrés. Tous les paramètres de journal spécifiques au point de terminaison sont appliqués en premier et peuvent ensuite être remplacés dans ces rappels. Une implémentation peut :
- Inspecter une requête ou une réponse.
- Activer ou désactiver un HttpLoggingFields quelconque.
- Ajuster la quantité de données du corps des requêtes ou des réponses journalisées.
- Ajouter des champs personnalisés aux fichiers de log.
Inscrire une implémentation IHttpLoggingInterceptor en appelant AddHttpLoggingInterceptor dans Program.cs. Si plusieurs instances IHttpLoggingInterceptor sont inscrites, elles sont exécutées dans l’ordre dans lequel elles ont été enregistrées.
L'exemple suivant montre comment enregistrer une implémentation IHttpLoggingInterceptor :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();
L'exemple suivant est une implémentation IHttpLoggingInterceptor qui :
- Inspecte la méthode de requête et désactive la journalisation des requêtes POST.
- Pour les requêtes non POST :
- Rédige le chemin de requête, les en-têtes de requête et les en-têtes de réponse.
- Ajoute des champs personnalisés et des valeurs de champ aux journaux de requête et de réponse.
using Microsoft.AspNetCore.HttpLogging;
namespace HttpLoggingSample;
internal sealed class SampleHttpLoggingInterceptor : IHttpLoggingInterceptor
{
public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
{
if (logContext.HttpContext.Request.Method == "POST")
{
// Don't log anything if the request is a POST.
logContext.LoggingFields = HttpLoggingFields.None;
}
// Don't enrich if we're not going to log any part of the request.
if (!logContext.IsAnyEnabled(HttpLoggingFields.Request))
{
return default;
}
if (logContext.TryDisable(HttpLoggingFields.RequestPath))
{
RedactPath(logContext);
}
if (logContext.TryDisable(HttpLoggingFields.RequestHeaders))
{
RedactRequestHeaders(logContext);
}
EnrichRequest(logContext);
return default;
}
public ValueTask OnResponseAsync(HttpLoggingInterceptorContext logContext)
{
// Don't enrich if we're not going to log any part of the response
if (!logContext.IsAnyEnabled(HttpLoggingFields.Response))
{
return default;
}
if (logContext.TryDisable(HttpLoggingFields.ResponseHeaders))
{
RedactResponseHeaders(logContext);
}
EnrichResponse(logContext);
return default;
}
private void RedactPath(HttpLoggingInterceptorContext logContext)
{
logContext.AddParameter(nameof(logContext.HttpContext.Request.Path), "RedactedPath");
}
private void RedactRequestHeaders(HttpLoggingInterceptorContext logContext)
{
foreach (var header in logContext.HttpContext.Request.Headers)
{
logContext.AddParameter(header.Key, "RedactedHeader");
}
}
private void EnrichRequest(HttpLoggingInterceptorContext logContext)
{
logContext.AddParameter("RequestEnrichment", "Stuff");
}
private void RedactResponseHeaders(HttpLoggingInterceptorContext logContext)
{
foreach (var header in logContext.HttpContext.Response.Headers)
{
logContext.AddParameter(header.Key, "RedactedHeader");
}
}
private void EnrichResponse(HttpLoggingInterceptorContext logContext)
{
logContext.AddParameter("ResponseEnrichment", "Stuff");
}
}
Avec cet intercepteur, une requête POST ne génère aucun journal même si la journalisation HTTP est configurée pour journaliser HttpLoggingFields.All. Une requête GET génère des journaux similaires à l’exemple suivant :
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
Request:
Path: RedactedPath
Accept: RedactedHeader
Host: RedactedHeader
User-Agent: RedactedHeader
Accept-Encoding: RedactedHeader
Accept-Language: RedactedHeader
Upgrade-Insecure-Requests: RedactedHeader
sec-ch-ua: RedactedHeader
sec-ch-ua-mobile: RedactedHeader
sec-ch-ua-platform: RedactedHeader
sec-fetch-site: RedactedHeader
sec-fetch-mode: RedactedHeader
sec-fetch-user: RedactedHeader
sec-fetch-dest: RedactedHeader
RequestEnrichment: Stuff
Protocol: HTTP/2
Method: GET
Scheme: https
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
Content-Type: RedactedHeader
MyResponseHeader: RedactedHeader
ResponseEnrichment: Stuff
StatusCode: 200
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[4]
ResponseBody: Hello World!
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[8]
Duration: 2.2778ms
Configuration de l’ordre de priorité de la journalisation
La liste suivante montre l’ordre de priorité pour la configuration de la journalisation :
- Configuration globale à partir de HttpLoggingOptions, définie en appelant AddHttpLogging.
- La configuration spécifique au point de terminaison à partir de l’attribut
[HttpLogging]ou de la méthode d'extension WithHttpLogging remplace la configuration globale. -
IHttpLoggingInterceptorest appelé avec les résultats et peut modifier davantage la configuration par requête.
La journalisation HTTP est un middleware qui journalise des informations sur les requêtes HTTP entrantes et les réponses HTTP. La journalisation HTTP fournit les logs suivants :
- Informations sur les requêtes HTTP
- Propriétés communes
- Headers
- Body
- Informations de réponse HTTP
La journalisation HTTP est utile dans plusieurs scénarios :
- Enregistrer des informations sur les requêtes entrantes et les réponses.
- Filtrer les parties des requêtes et des réponses enregistrées.
- Filtrage des en-têtes à journaliser.
La journalisation HTTP peut réduire les performances d’une application, en particulier lors de la journalisation des corps de requête et de réponse. Tenez compte de l’impact sur les performances lorsque vous sélectionnez les champs à journaliser. Testez l’impact des propriétés de journalisation sélectionnées sur les performances.
Warning
La journalisation HTTP peut potentiellement journaliser des informations d’identification personnelle. Tenez compte des risques, et évitez de journaliser des informations sensibles.
Activation de la journalisation HTTP
La journalisation HTTP est activée avec UseHttpLogging, qui ajoute un middleware de journalisation HTTP.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Hello World!");
app.Run();
Par défaut, la journalisation HTTP journalise les propriétés courantes telles que le chemin, le code d’état et les en-têtes des requêtes et des réponses. Ajoutez la ligne suivante au fichier appsettings.Development.json au niveau "LogLevel": { afin que les logs HTTP soient affichés :
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
La sortie est journalisée comme message unique à LogLevel.Information.
Options de journalisation HTTP
Pour configurer le middleware de journalisation HTTP, appelez AddHttpLogging dans Program.cs.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Note
Dans l’exemple précédent et les exemples suivants, UseHttpLogging est appelé après UseStaticFiles, la journalisation HTTP n’est donc pas activée pour le fichier statique. Pour activer la journalisation HTTP de fichier statique, appelez UseHttpLogging avant UseStaticFiles.
LoggingFields
HttpLoggingOptions.LoggingFields est un indicateur d’énumération qui configure certaines parties de la requête et de la réponse à journaliser.
HttpLoggingOptions.LoggingFields a la valeur par défaut RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
Headers sont un ensemble d’en-têtes de requête HTTP autorisés à être journalisés. Les valeurs d’en-tête sont journalisées uniquement pour les noms d’en-tête qui se trouvent dans cette collection. Le code suivant journalise l’en-tête de requête "sec-ch-ua". Si logging.RequestHeaders.Add("sec-ch-ua"); est supprimé, la valeur de l’en-tête de requête "sec-ch-ua" sera supprimée. Le code mis en évidence ci-dessous appelle HttpLoggingOptions.RequestHeaders et HttpLoggingOptions.ResponseHeaders :
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
MediaTypeOptions
MediaTypeOptions fournit la configuration permettant de sélectionner l’encodage à utiliser pour un type de média spécifique.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Cette approche peut également être utilisée pour activer la journalisation des données qui ne sont pas journalisées par défaut. Par exemple, les données de formulaire, qui peuvent avoir un type de média tel que application/x-www-form-urlencoded ou multipart/form-data.
Méthodes MediaTypeOptions
RequestBodyLogLimit et ResponseBodyLogLimit
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Rédaction de données sensibles
La journalisation Http peut être activée avec masquage des données sensibles en appelant AddHttpLoggingRedaction:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op => { });
Pour plus d'informations sur la bibliothèque de rédaction des données .NET, consultez la rédaction des données dans .NET.
Options de rédaction de journalisation
Pour configurer les options de journalisation avec rédaction, appelez AddHttpLoggingRedaction dans Program.cs à l'aide d'une lambda pour configurer LoggingRedactionOptions:
using Microsoft.Extensions.Compliance.Classification;
namespace HttpLoggingSample
{
public static class MyTaxonomyClassifications
{
public static string Name => "MyTaxonomy";
public static DataClassification Private => new(Name, nameof(Private));
public static DataClassification Public => new(Name, nameof(Public));
public static DataClassification Personal => new(Name, nameof(Personal));
}
}
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
Avec la configuration de redaction précédente, la sortie est similaire à ce qui suit :
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[9]
Request and Response:
server.address: localhost:61361
Path: /
http.request.header.accept:
Protocol: HTTP/2
Method: GET
Scheme: https
http.response.header.content-type:
StatusCode: 200
Duration: 8.4684
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/2 GET https://localhost:61361/ - 200 - text/plain;+charset=utf-8 105.5334ms
Note
Le chemin de la demande /home n'est pas journalisé, comme il est inclus dans la propriété ExcludePathStartsWith.
http.request.header.accept et http.response.header.content-type ont été censurés par Microsoft.Extensions.Compliance.Redaction.ErasingRedactor.
RequestPathLoggingMode
RequestPathLoggingMode détermine la façon dont le chemin d’accès de la requête est enregistré, qu’il soit Formatted ou Structureddéfini par IncomingPathLoggingMode:
-
Formatted: enregistre le chemin de la requête sans paramètres. -
Structured: enregistre le chemin de la requête avec les paramètres inclus.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
RequestPathParameterRedactionMode
RequestPathParameterRedactionMode spécifie la façon dont les paramètres de routage dans le chemin de requête doivent être masqués, qu’ils soient Strict, Loose ou None, définis par HttpRouteParameterRedactionMode.
-
Strict: les paramètres d’itinéraire de requête sont considérés comme sensibles, nécessitent une annotation explicite avec une classification des données et sont adoptés par défaut. -
Loose: tous les paramètres sont considérés comme non sensibles et inclus as-is par défaut. -
None: les paramètres de routage ne sont pas caviardés, indépendamment de la présence d’annotations de classification des données.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
RequestHeadersDataClasses
RequestHeadersDataClasses mappe les en-têtes de requête à leur classification des données, ce qui détermine la façon dont ils sont supprimés :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
ResponseHeadersDataClasses
ResponseHeadersDataClasses, similaire à RequestHeadersDataClasses« mais pour les en-têtes de réponse :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
RouteParameterDataClasses
RouteParameterDataClasses mappe les paramètres de routage à leur classification des données :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
ExcludePathStartsWith
ExcludePathStartsWith spécifie les chemins qui doivent être entièrement exclus de la journalisation.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
IncludeUnmatchedRoutes
IncludeUnmatchedRoutes permet de signaler des itinéraires non correspondants. Si la valeur est définie true, enregistre l'ensemble du chemin des routes non identifiées par le routage au lieu d'enregistrer la valeur Unknown pour l'attribut de chemin :
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();