Incapable de s'authentifier ASP.NET service D'Api Web avec HttpClient
j'ai un ASP.NET service D'API Web qui s'exécute sur un serveur web avec authentification Windows activée.
j'ai un site client construit sur MVC4 qui tourne sur un autre site sur le même serveur web qui utilise le HttpClient pour extraire des données du service. Ce site client fonctionne avec l'usurpation d'identité activée et utilise également l'authentification windows.
le serveur web est Windows Server 2008 R2 avec IIS 7.5.
le le défi que j'ai à relever consiste à faire passer le client HttpClient à l'utilisateur windows actuel dans le cadre de son processus d'authentification. J'ai configuré le HttpClient de cette manière:
var clientHandler = new HttpClientHandler();
clientHandler.UseDefaultCredentials = true;
clientHandler.PreAuthenticate = true;
clientHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
var httpClient = new HttpClient(clientHandler);
ma compréhension est que l'exécution du site avec l'usurpation d'identité activée et ensuite construire le client de cette manière devrait se traduire par le client authentifiant au service en utilisant l'identité usurpée de l'utilisateur actuellement connecté.
ce n'est pas happening. En fait, le client ne semble pas s'authentifier du tout.
Le service est configuré pour utiliser l'authentification windows et cela semble fonctionner parfaitement. Je peux aller à http://server/api/shippers dans mon navigateur web et être invité pour l'authentification windows, une fois entré je reçois les données demandées.
dans les journaux de L'IIS, je vois que les requêtes API sont reçues sans authentification et reçoivent une contestation 401 réponse.
la Documentation sur celui-ci semble être clairsemée.
j'ai besoin d'un aperçu de ce qui pourrait être mal ou une autre façon d'utiliser l'authentification windows avec cette application.
Merci, Craig
4 réponses
j'ai étudié le code source de HttpClientHandler (la dernière version sur laquelle j'ai pu mettre la main) et c'est ce que l'on peut trouver dans la méthode SendAsync:
// BeginGetResponse/BeginGetRequestStream have a lot of setup work to do before becoming async
// (proxy, dns, connection pooling, etc). Run these on a separate thread.
// Do not provide a cancellation token; if this helper task could be canceled before starting then
// nobody would complete the tcs.
Task.Factory.StartNew(startRequest, state);
maintenant si vous vérifiez dans votre code la valeur de SecurityContext.IsWindowsIdentityFlowSuppressed (), vous serez plus que probablement vous vrai. Dans le résultat la méthode StartRequest est exécutée dans le nouveau thread avec les lettres de créance de la asp.net processus (pas les justificatifs d'identité de l'utilisateur usurpé).
il y a deux façons possibles de s'en sortir. Si vous avez accès à votre serveur aspnet_config.config, vous devez définir les paramètres suivants (ceux du web).config semble n'avoir aucun effet):
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
si vous ne pouvez pas changer aspnet_config.config vous devrez créer votre propre HttpClientHandler pour supporter ce scénario.
MISE À JOUR CONCERNANT L'UTILISATION DE FQDN
le question vous avez frappé ici est une fonctionnalité de Windows qui est conçu pour protéger contre "les attaques par réflexion". Pour contourner cela, vous avez besoin de la liste blanche le domaine que vous essayez d'accès sur l'ordinateur qui tente d'accéder au serveur. Suivez les étapes ci-dessous:
- Allez dans Démarrer --> Exécuter --> regedit
- Localiser
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
clé de registre. - droit-cliquez dessus, choisissez Nouveau et puis Multi-Chaîne De Valeur .
- Type
BackConnectionHostNames
( entrer ). - faites un clic droit sur la valeur créée et choisissez Modifiez .
- mettez le(S) nom(s) d'hôte pour le (s) site (s) qui sont sur l'ordinateur local dans la boîte de valeur et cliquez sur OK (chaque nom d'hôte/FQDN doit être sur sa propre ligne, pas de jokers, le nom doit être identique).
- de tout Enregistrer et redémarrer la machine
vous pouvez lire L'article complet de KB concernant la question ici .
j'avais aussi ce même problème. Grâce aux recherches effectuées par @tpeczek, j'ai développé la solution suivante: au lieu d'utiliser le HttpClient (qui crée des threads et envoie des requêtes async), j'ai utilisé la classe WebClient qui émet des requêtes sur le même thread. Cela me permet de transmettre L'identité de L'utilisateur à WebAPI à partir d'un autre ASP.NET application.
l'inconvénient évident est que cela ne fonctionnera pas async.
var wi = (WindowsIdentity)HttpContext.User.Identity;
var wic = wi.Impersonate();
try
{
var data = JsonConvert.SerializeObject(new
{
Property1 = 1,
Property2 = "blah"
});
using (var client = new WebClient { UseDefaultCredentials = true })
{
client.Headers.Add(HttpRequestHeader.ContentType, "application/json; charset=utf-8");
client.UploadData("http://url/api/controller", "POST", Encoding.UTF8.GetBytes(data));
}
}
catch (Exception exc)
{
// handle exception
}
finally
{
wic.Undo();
}
Note: nécessite un paquet NuGet: Newtonsoft.Json, qui est le même JSON serializer WebAPI utilise.
la raison pour laquelle cela ne fonctionne pas est que vous avez besoin d'une authentification à double saut.
le premier saut est le serveur web, Obtenir l'usurpation d'identité avec l'authentification Windows pour fonctionner il n'y a pas de problème. Mais lorsque vous utilisez HttpClient ou WebClient pour vous authentifier sur un autre serveur, le serveur web doit fonctionner sur un compte qui a la permission de faire la délégation nécessaire.
voir ci-dessous pour plus de détails:
http://blogs.technet.com/b/askds/archive/2008/06/13/understanding-kerberos-double-hop.aspx
correction à l'aide de la commande" setspn":
http://www.phishthis.com/2009/10/24/how-to-configure-ad-sql-and-iis-for-two-hop-kerberos-authentication-2 /
(Vous aurez besoin des droits d'accès suffisants pour effectuer ces opérations.)
il suffit de considérer ce qui se passerait si n'importe quel serveur était autorisé à transmettez vos lettres de créance comme bon vous semble... Pour éviter ce problème de sécurité, le contrôleur de domaine doit savoir quels comptes sont autorisés à effectuer la délégation.
pour se faire passer pour l'utilisateur original (authentifié), utilisez la configuration suivante sur le Web.fichier de configuration:
<authentication mode="Windows" />
<identity impersonate="true" />
avec cette configuration, ASP.NET il imite toujours l'utilisateur authentifié, et tout accès aux ressources est effectué en utilisant le contexte de sécurité de l'utilisateur authentifié.