J'ai asp.net application de base. Je souhaite utiliser le modèle IOptions
pour injecter les valeurs de appsettings.json. J'ai donc une classe SecurityHeaderOptions
et une classe cible SecurityHeadersBuilder
dont le constructeur prend IOptions<SecurityHeaderOptions>
en tant que paramètre.
Je sais que .net core peut implicitement créer une instance de SecurityHeadersBuilder
en injectant IOptions<SecurityHeaderOptions>
après avoir enregistré les deux avec le conteneur.
Cependant, je veux explicitement créer une instance de SecurityHeadersBuilder
, appeler l'une de ses méthodes et ensuite enregistrer l'instance avec le conteneur.
public sealed class SecurityHeaderOptions
{
public string FrameOption { get; set; }
public string XssProtection { get; set; }
}
public class SecurityHeadersBuilder
{
private readonly SecurityHeaderOptions _options = null;
public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
{
_options = options.Value;
}
public SecurityHeadersBuilder AddDefaultPolicy()
{
AddFrameOptions();
AddConetntSecurityPolicy();
return this;
}
}
Méthode ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));
services.AddScoped<SecurityHeadersBuilder>(provider =>
new SecurityHeadersBuilder(?????).AddDefaultPolicy())
}
Des questions
1> Si je passe explicitement des options au constructeur, dois-je enregistrer SecurityHeaderOptions
avec le conteneur en utilisant la méthode service.Configure
?
2> Configuration.GetSection("SecurityHeaderOptions")
ne peut pas renvoyer l'instance de IOptions<SecurityHeaderOptions>
, mais renvoie IConfigurationSection
?
3> Quoi qu’il en soit, comment puis-je récupérer et passer SecurityHeaderOptions
dans le constructeur de SecurityHeadersBuilder
?
En utilisant .NET Core 2 et n'ayant pas de fournisseur disponible (ou souhaitant l'ajouter) dans ConfigureServices
, j'ai opté pour quelque chose comme ceci (en utilisant le code OP comme exemple):
public void ConfigureServices(IServiceCollection services)
{
// secOpts available for use in ConfigureServices
var secOpts = Configuration
.GetSection("SecurityHeaderOptions")
.Get<SecurityHeaderOptions>();
...
}
C’est ainsi que j’enregistre des options et que j’injecte dans SecurityHeadersBuilder
public void ConfigureServices(IServiceCollection services)
{
services.Configure<SecurityHeaderOptions>(Configuration.GetSection("SecurityHeaderOptions"));
services.AddScoped<SecurityHeadersBuilder>(provider =>
{
var option = provider.GetService<IOptions<SecurityHeaderOptions>>();
return new SecurityHeadersBuilder(option)
.AddDefaultPolicy();
});
}
Concernant vos questions:
1. Oui, vous devez enregistrer les options, mais je crois que vous le faites de la mauvaise façon (du moins selon votre exemple). Vous devriez vous enregistrer comme ceci:
services.Configure<SecurityHeaderOptions>(options => Configuration.GetSection("SecurityHeaderOptions").Bind(options));
2. Je crois que l'enregistrement correct auquel je fais référence ci-dessus renvoie ce que vous attendez.
3. Il suffit de l'enregistrer et de le placer sur le constructeur SecurityHeaderBuilder
. Vous n'avez pas besoin (le conteneur par défaut .NET Core IOC ne le permet pas non plus) de passer des paramètres de constructeur lors de son enregistrement. Pour cela, vous devrez utiliser d'autres IOC, tels qu'Autofac.
Mais vous devez vous inscrire SecurityHeadersBuilder
pour pouvoir l’utiliser dans d’autres classes ..__ Utilisez simplement une interface pour cela.
public interface ISecurityHeadersBuilder
{
SecurityHeadersBuilder AddDefaultPolicy;
}
public class SecurityHeadersBuilder : ISecurityHeadersBuilder
{
private readonly SecurityHeaderOptions _options = null;
public SecurityHeadersBuilder(IOptions<SecurityHeaderOptions> options)
{
_options = options.Value;
}
public SecurityHeadersBuilder AddDefaultPolicy()
{
AddFrameOptions();
AddContentSecurityPolicy();
return this;
}
}
Ensuite, enregistrez-le simplement dans startup.cs
comme ceci
services.AddScoped<ISecurityHeadersBuilder, SecurityHeadersBuilder>();