J'ai une application Web ASP.NET Core 2.1 avec des pages Razor qui a des informations d'authentification AAD définies dans le appsettings.json
fichier (gracieuseté du modèle d'application par défaut - voir ci-dessous comment j'y suis arrivé). Cependant, lorsque vous essayez de configurer l'authentification dans Startup.cs
la configuration n'a aucune des valeurs de configuration de mon appsettings.json
. Si j'inspecte l'objet IConfiguration
dans le débogueur, il semble n'avoir que les configurations de variables d'environnement:
Ici se trouve le Startup.ConfigureServices
méthode où réside le problème:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options =>
{
// This is from the default template. It should work, but the relevant settings aren't there so options isn't populated.
this.Configuration.Bind("AzureAd", options);
// This of course works fine
options.Instance = "MyInstance";
options.Domain = "MyDomain";
options.TenantId = "MyTenantId";
options.ClientId = "MyClientId";
options.CallbackPath = "MyCallbackPath";
});
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
Et la configuration du service au cas où cela serait important (notez que cela est construit au-dessus d'un service sans état de structure de service):
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder()
.UseKestrel(opt =>
{
int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
{
listenOptions.UseHttps(GetCertificateFromStore());
listenOptions.NoDelay = true;
});
})
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
};
}
Pour créer ce service, j'ai utilisé l'assistant dans VS2017. J'ai sélectionné un projet de structure de service existant (.sfproj
) et choisi Services > Add > New Service Fabric Service
et a choisi Stateless ASP.NET Core [for .NET Framework]
, puis sur la page suivante, j'ai choisi Web Application
(celui avec Razor Pages, pas MVC) et cliqué sur Change Authentication
où j'ai choisi Work or School Accounts
et entré mes informations AAD. Les seules modifications que j'ai apportées à ce modèle étaient l'ajout du code à l'intérieur de l'appel à AddAzureAD
dans Startup.ConfigureServices
et en définissant le appsettings.json
fichiers à toujours copier dans le répertoire de sortie.
Pourquoi le appsettings.json
le fichier est-il chargé dans la configuration? Si je comprends bien, cela est censé se produire par défaut, mais quelque chose semble manquer ...
WebHostBuilder
ne se charge pas appsettings.json
par défaut, vous devez appeler manuellement AddJsonFile
. Par exemple:
return new WebHostBuilder()
.UseKestrel(opt =>
{
//snip
})
.ConfigureAppConfiguration((builderContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: false);
})
.ConfigureServices(
services => services
.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
Vous pouvez également utiliser WebHost.CreateDefaultBuilder
qui chargera plus de valeurs par défaut.
Une autre approche serait de créer manuellement la configuration via ConfigurationBuilder
puis d'utiliser la méthode UseConfiguration
.
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true)
.Build();
var Host = new WebHostBuilder()
.UseConfiguration(configuration)
.UseKestrel()
.UseStartup<Startup>();
L'intention principale est essentielle pour fournir un peu de flexibilité lors de la mise en œuvre, ils font souvent erreur sur less is more. Vous devez dire explicitement ce que vous souhaitez, de cette façon le pipeline reste relativement petit.