2010-10-26 20 views
18

Comment puis-je mettre en œuvre suivante dans l'application ASP.NET MVC:Comment prendre en charge l'authentification NTLM avec fallback pour se former dans ASP.NET MVC?

  1. utilisateur ouvre un site intranet
  2. utilisateur est silencieusement authentifié si possible
  3. si l'authentification NTLM n'a pas fonctionné, formulaire de connexion show à l'utilisateur
  4. utilisateur indiquent connecter mot de passe et le domaine de sélection dans la liste de domaines prédéfinis
  5. utilisateur est authentifié dans le code en utilisant AD

Je sais implémenter 4 et 5 mais je ne trouve pas d'informations sur la façon de combiner NTLM et les formulaires. Ainsi, cette boîte de dialogue de connexion/mot de passe NTLM natif n'est jamais affichée - authentification transparente ou page de connexion agréable.

Comment devrait fonctionner? Faut-il demander à l'utilisateur un identifiant et un mot de passe? Est-ce que ses informations d'identification actuelles (nom d'utilisateur du domaine) peuvent être utilisées sans demander à entrer le nom d'utilisateur et le mot de passe?

Mise à jour pour ces derniers, enquête même problème:

Quand je demandais ce que je n'était pas complètement comprendre comment fonctionne l'authentification NTLM interne. Il est important de comprendre ici que si le navigateur de l'utilisateur ne supporte pas NTLM correctement ou si le support NTLM est désactivé par l'utilisateur, le serveur n'aura jamais l'occasion de contourner ce problème.

Comment l'authentification Windows fonctionne:

  1. client envoie une requête HTTP régulière au serveur
  2. Server répond avec l'état HTTP 401 et l'indication que l'authentification NTLM doit être utilisé pour accéder aux ressources
  3. client envoyer NTLM Message de type 1
  4. Le serveur répond avec le message NTLM Type2 avec le défi
  5. Le client envoie le message Type3 avec la réponse au défi
  6. Server répond avec le contenu réel demandé

Comme vous le voyez, le navigateur ne supportant pas NTLM ne passera pas à l'étape (3), au lieu utilisateur sera affiché IIS généré erreur 401 page.

Si l'utilisateur n'a pas d'informations d'identification, après l'annulation de l'authentification NTLM, le navigateur de fenêtre de dialogue contextuel ne continuera pas à (3) également. Nous n'avons donc aucune chance de rediriger automatiquement les utilisateurs vers une page de connexion personnalisée.

La seule option ici est d'avoir une page "passerelle" où nous décidons si l'utilisateur doit supporter NTLM et si c'est le cas, rediriger vers la page d'accueil protégée NTLM.

Si ce n'est pas le cas, affichez le formulaire de connexion et autorisez l'authentification en entrant manuellement le nom d'utilisateur et le mot de passe.

La décision est généralement prise en fonction de l'adresse IP et/ou du nom d'hôte des utilisateurs, soit en faisant correspondre les plages d'adresses IP, soit en consultant le tableau des adresses IP prédéfinies.

+0

http: // stackoverflow. com/questions/492977/anonymous-access-et-ntlm-authentication-in-iis –

Répondre

8

Cet article peut vous aider à vous orienter dans la bonne direction. Fondamentalement, vous avez deux applications dans deux répertoires virtuels sous le même nom d'hôte. Une application utilise l'authentification par formulaire, une utilise Windows. Celui qui utilise l'authentification Windows crée un cookie d'authentification de formulaire valide et redirige vers le second répertoire virtuel.

ASP.NET Mixed Mode Authentication

0

Vous ne pouvez pas avoir les deux NTLM et FormsAuthentication dans la même application ASP.NET. Vous aurez besoin de deux applications différentes dans des répertoires virtuels distincts.

+6

Pas tout à fait vrai - vous ne pouvez pas configurer (en utilisant web.config) une application pour prendre en charge à la fois l'authentification NTLM et Forms, mais il n'y a aucune raison Ne créez pas un module d'authentification personnalisé pour le gérer. – Keith

2

J'ai cette configuration exacte en production, j'ai configuré mon portail pour utiliser FormsAuth et ai écrit une fonction qui prend l'IP des visiteurs pour rechercher le compte d'utilisateur qui est connecté à cet IP/PC. En utilisant le nom que je trouve (par exemple DOMAIN\user), je vérifie que le domaine correspond à mon domaine et que le nom d'utilisateur/compte est valide dans mon fournisseur FormsAth en utilisant Membership.GetUser(<user>). Si cet appel renvoie une correspondance et que l'utilisateur IsApproved crée un cookie FormsAuthenticationTicket & pour l'utilisateur. J'ai plus de 400 personnes sur le réseau et cela fonctionne parfaitement, les seuls ordinateurs qui se connectent encore sont (1. Les utilisateurs sans comptes dans mon portail, 2. Quelques utilisateurs MAC/Linux, 3. Les utilisateurs mobiles qui n'ont pas démarré sur le réseau et avait la stratégie de groupe activer leur pare-feu à haute).

Le hic à cette solution est qu'elle nécessite usurpation d'identité d'un compte administrateur de domaine pour interroger les utilisateurs PC et que vous utilisez le code non géré netapi32.dll.

Voici le code que j'utilise (appels de fonctions externes non fournis, par souci de brièveté). J'ai essayé de simplifier un peu, car il y a BEAUCOUP d'appels externes.

string account = String.Empty; 
string domain = String.Empty; 
string user = String.Empty; 


ImpersonateUser iu = new ImpersonateUser(); //Helper that Enabled Impersonation 
if (iu.impersonateValidUser(StringHelper.GetAppSetting("DomainAccount"), StringHelper.GetAppSetting("DomainName"), StringHelper.GetEncryptedAppSetting("DomainAccountPassword"))) 
{ 
    NetWorkstationUserEnum nws = new NetWorkstationUserEnum(); //Wrapper for netapi32.dll (Tested on Vista, XP, Win2K, Win2K3, Win2K8) 
    string host = nws.DNSLookup(Request.UserHostAddress); // netapi32.dll requires a host name, not an IP address 

    string[] users = nws.ScanHost(host); // Gets the users/accounts logged in 

    if (nws.ScanHost(host).Length > 0) 
    { 
     string workstationaccount = string.Empty; 

     if (host.IndexOf('.') == -1) // Pick which account to use, I have 99.9% success with this logic (only time doesn't work is when you run a interactive process as a admin e.g. Run As <process>). 
     { 
      workstationaccount = String.Format("{0}\\{1}$",StringHelper.GetAppSetting("DomainName"), host).ToUpper(); 
     } 
     else 
     { 
      workstationaccount = String.Format("{0}\\{1}$", StringHelper.GetAppSetting("DomainName"), host.Substring(0, host.IndexOf('.'))).ToUpperInvariant(); 
     } 

     account = users[users.Length - 1].Equals(workstationaccount) ? users[0] : users[users.Length - 1]; 

     domain = account.Substring(0, account.IndexOf("\\")); 
     user = account.Substring(account.IndexOf("\\") + 1, 
           account.Length - account.IndexOf("\\") - 1); 
    } 

    iu.undoImpersonation(); // Disable Impersonation 
} 

Maintenant, en utilisant le compte nous avons pris dans la première fonction/processus, nous essayons maintenant de vérifier et de décider si nous devons montrer une connexion ou une connexion automatique à l'utilisateur.

MembershipUser membershipUser = Membership.GetUser(user); 

if (membershipUser != null && membershipUser.IsApproved) 
{ 
    string userRoles = string.Empty; // Get all their roles 
    FormsAuthenticationUtil.RedirectFromLoginPage(user, userRoles, true); // Create FormsAuthTicket + Cookie + 
} 

j'ai écrit un billet de blog sur ce depuis longtemps, voici un lien vers l'enveloppe pour netapi32.dll et mon aide Impersonation que je fournis dans le poste Source Code Download

+1

je vous remercie pour votre réponse détaillée, je ne le marque pas encore comme réponse car je pense qu'il peut avoir des préoccupations avec la sécurité et dans l'ensemble a une sensation de «hack» :-) –

+1

Il est certainement un hack .. – Zachary