web-dev-qa-db-fra.com

L'authentification Windows ASP.NET Core 2.0 HttpSys échoue avec l'attribut Authorize (InvalidOperationException: aucun authentification n'a été spécifié)

J'essaie de migrer une application ASP.NET Core 1.1 vers ASP.NET Core 2.0.

L'application est assez simple et comprend les éléments suivants:

  • Hébergé sur HttpSys (anciennement WebListener)
  • Utilisation de l'authentification Windows: options.Authentication.Schemes = AuthenticationSchemes.NTLM
  • Autoriser l'authentification anonyme: options.Authentication.AllowAnonymous = true (car certains contrôleurs ne nécessitent pas d'authentification)
  • Les contrôleurs qui nécessitent une authentification sont décorés avec le [Authorize] attribut.

Le projet se compile et démarre très bien. Il sert également les actions des contrôleurs qui ne nécessitent pas d'authentification.

Cependant, dès que je frappe un contrôleur avec le [Authorize] attribut, j'obtiens l'exception suivante:

System.InvalidOperationException: No authenticationScheme was specified,
and there was no DefaultChallengeScheme found.
   at Microsoft.AspNetCore.Authentication.AuthenticationService.<ChallengeAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.ChallengeResult.<ExecuteResultAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeResultAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()

J'ai commencé à jouer avec les modèles de projet et j'ai remarqué que je pouvais facilement le reproduire en utilisant le modèle standard Application Web ASP.NET Core (Model-View-Controller) avec l'authentification Windows.

Le fichier Program.cs a été modifié comme suit:

    public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseHttpSys(options =>
            {
                options.Authentication.Schemes = AuthenticationSchemes.NTLM;
                options.Authentication.AllowAnonymous = true;
                options.MaxConnections = 100;
                options.MaxRequestBodySize = 30000000;
                options.UrlPrefixes.Add("http://localhost:5000");
            })
            .UseStartup<Startup>()
            .Build();

Cela vient directement de la documentation HttpSys . J'ai également ajouté le [Authorize] attribut à la classe HomeController. Maintenant, il produira exactement la même exception que celle illustrée.

J'ai trouvé des messages Stack Overflow connexes ( ici , ici et ici ), mais aucun d'eux ne traite de l'authentification Windows simple (et les réponses le font semblent pas généraliser).

18
Andreas

Lors de la rédaction de l'article, je me suis souvenu d'avoir rencontré cette sous-section du guide de migration. Il dit d'ajouter

services.AddAuthentication(Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme);

à la fonction ConfigureServices.

J'ai d'abord pensé que cela ne s'appliquerait pas à HttpSys, étant donné le nom complet de la constante (en particulier le IISIntegration m'a jeté). De plus, au moment d'écrire ces lignes, la documentation HttpSys omet complètement de le mentionner.

Pour ceux qui ciblent le .NET Framework complet, cela nécessite d'installer le Microsoft.AspNetCore.Authentication Package NuGet.

[~ # ~] modifier [~ # ~]

Comme le souligne Tratcher, il existe une constante similaire de l'espace de noms HttpSys que vous devriez plutôt utiliser:

Microsoft.AspNetCore.Server.HttpSys.HttpSysDefaults.AuthenticationScheme
26
Andreas

La réponse d'Andreas m'a mis sur la bonne voie mais c'est ce qui a fonctionné pour moi:

Ajout d'une référence de package à Microsoft.AspNetCore.Authentication

puis pour Startup.cs

using Microsoft.AspNetCore.Server.IISIntegration;

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddAuthentication(IISDefaults.AuthenticationScheme);
    ...
}
7
fiat

Une autre chose, si vous avez déjà ajouté services.AddAuthentication (IISDefaults.AuthenticationScheme); assurez-vous d'activer un type d'authentification (fenêtres, formulaires) dans iis sous l'application -> authentification. Les miens étaient tous désactivés et obtenaient cette erreur même avec le code en place.

1
joel1618