24 votes

Auto-hébergement de l'API Web ASP.NET avec authentification Windows

J'essaie d'utiliser l'option ASP.NET Web API Self-Host avec l'authentification Windows afin de pouvoir déterminer l'utilisateur connecté et finalement accepter ou rejeter l'utilisateur en fonction de son identité. Voici le code de mon application console :

using System;
using System.Web.Http;
using System.Web.Http.SelfHost;

namespace SelfHost
{
    class Program
    {
        static void Main(string[] args)
        {
            var config = new HttpSelfHostConfiguration("http://myComputerName:8080");
            config.UseWindowsAuthentication = true;

            config.Routes.MapHttpRoute(
                "API Default", "api/{controller}/{id}",
                new { id = RouteParameter.Optional });

            using (HttpSelfHostServer server = new HttpSelfHostServer(config))
            {
                server.OpenAsync().Wait();

                Console.WriteLine("Press Enter to quit.");
                Console.ReadLine();
            }
        }
    }
}

Voici le contrôleur :

[Authorize]
public class HelloController : ApiController
{
    public string Get()
    {
        // This next line throws an null reference exception if the Authorize
        // attribute is commented out.
        string userName = Request.GetUserPrincipal().Identity.Name;
        return "Hello " + userName;
    }
}

Edit - J'ai ajouté l'attribut Authorize, et le débogueur montre que le code à l'intérieur de la méthode d'action Get n'est jamais invoqué. Le code HTML suivant est renvoyé :

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=windows-1252" http-equiv=Content-Type></HEAD>
<BODY></BODY></HTML>

Si l'attribut Authorize est commenté, Request.GetUserPrincipal().Identity.Name lance une exception de référence nulle étant donné que Request.GetUserPrincipal() donne un résultat nul.

25voto

tpeczek Points 12722

J'ai également rencontré ce problème et la seule solution que j'ai trouvée est de fournir une configuration HttpSelfHostedConfiguration dédiée :

public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration
{
    public NtlmSelfHostConfiguration(string baseAddress)
        : base(baseAddress)
    { }

    public NtlmSelfHostConfiguration(Uri baseAddress)
        : base(baseAddress)
    { }

    protected override BindingParameterCollection OnConfigureBinding(HttpBinding httpBinding)
    {
        httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
        httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;
        return base.OnConfigureBinding(httpBinding);
    }
}

Pour l'utiliser, il suffit de modifier une ligne (il n'est plus nécessaire d'activer UseWindowsAuthentication) :

var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");

Le seul problème de cette approche est que l'authentification est désormais requise pour chaque requête adressée au serveur qui utilise cette configuration.

3voto

Dreamer Points 921

J'ai hébergé "Web API" dans un service Windows et voici ce que j'ai fait pour prendre en charge l'authentification Windows (en me basant sur la question ci-dessus, les réponses, certains articles connexes - je consolide simplement car cela peut être utile à d'autres).

Serveur HTTP (api web) :

Set (référence : http://msdn.microsoft.com/en-us/library/system.web.http.selfhost.httpselfhostconfiguration.clientcredentialtype(v=vs.118).aspx ),

HttpSelfHostConfiguration.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;

@Client :

Puis, comme Allan l'a mentionné (ci-dessus), réglez UseDefaultCredentials sur true.

Utilisation de HttpClient :

var handler = new HttpClientHandler();
    handler.UseDefaultCredentials = true;
    _httpClient = new HttpClient(handler);

Utilisation de WebClient (référence : http://msdn.microsoft.com/en-us/library/system.net.webclient.usedefaultcredentials.aspx )

fixer à "true" le paramètre usedefaultcrednetials de webclient.

Meilleures salutations !

3voto

IdahoSixString Points 532

Je suis un peu en retard sur ce sujet. Cependant, si vous utilisez Owin pour faire de l'auto-hébergement et que vous avez besoin de l'authentification Windows. Dans votre classe de démarrage, vous pouvez ajouter ce qui suit.

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        HttpListener listener = (HttpListener)app.Properties["System.Net.HttpListener"];
        listener.AuthenticationSchemes = AuthenticationSchemes.IntegratedWindowsAuthentication;
    }
}

2voto

Szilard Muzsi Points 866

Êtes-vous sûr d'avoir franchi l'étape de l'authentification ? Vous pourriez utiliser violoniste pour vérifier si les demandes aboutissent réellement ou si le serveur répond toujours par 401 Unauthorized (puisque vous utilisez l'authentification).

Vous pouvez également essayer de mettre en œuvre votre propre AuthorizeAttribute et y placer des points d'arrêt pour s'assurer qu'il est touché (vous voudrez surcharger l'option OnAuthorization et voir si elle est touchée).

using System.Web.Http;
public class MyAuth : AuthorizeAttribute
{
    public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        base.OnAuthorization(actionContext); //put breakpoint here
    }
}

Assurez-vous également que vous utilisez la fonction Authorize de l'attribut System.Web.Http et non de System.Web.Mvc . Voir aquí pourquoi.

2voto

mheyman Points 795

Similaire à tpeczek mais mise à jour pour refléter l'utilisation de HTTPS. tpeczek ne fonctionne pas pour HTTPS parce que l'appel à base.OnConfigureBinding(httpBinding); avec HTTPS écrase les modifications. En outre, vous ne pouvez pas utiliser httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly; avec HTTPS.

Utiliser une configuration HttpSelfHost personnalisée :

public class NtlmSelfHostConfiguration : HttpSelfHostConfiguration
{
    public NtlmSelfHostConfiguration(string baseAddress)
        : base(baseAddress)
    { }

    public NtlmSelfHostConfiguration(Uri baseAddress)
        : base(baseAddress)
    { }

    protected override BindingParameterCollection OnConfigureBinding(
        HttpBinding httpBinding)
    {
        if (this.BaseAddress.Scheme == Uri.UriSchemeHttps)
        {
            var ret = base.OnConfigureBinding(httpBinding);
            httpBinding.Security.Transport.ClientCredentialType =
                HttpClientCredentialType.Ntlm;
            return ret;
        }

        httpBinding.Security.Mode = HttpBindingSecurityMode.TransportCredentialOnly;
        httpBinding.Security.Transport.ClientCredentialType = 
            HttpClientCredentialType.Ntlm;
        return base.OnConfigureBinding(httpBinding);
    }
}

Ensuite, vous pouvez faire

var config = new NtlmSelfHostConfiguration("http://myComputerName:8080");

ou

var config = new NtlmSelfHostConfiguration("https://myComputerName:8443");

pour obtenir une configuration à passer dans new HttpSelfHostServer(config)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X