Comment prendre en charge L'authentification NTLM avec repli vers form in ASP.NET MVC?

Comment puis-je mettre en oeuvre le suivi dans ASP.NET MVC application:

  1. l'utilisateur ouvre le site intranet
  2. l'utilisateur est authentifié en silence si possible
  3. si L'authentification NTLM n'a pas fonctionné, afficher le formulaire de connexion à l'utilisateur
  4. l'utilisateur indique le mot de passe de connexion et sélectionne le domaine dans la liste des domaines prédéfinis
  5. l'utilisateur est authentifié dans le code en utilisant AD

je sais comment implémenter les 4 et 5 mais je ne trouve pas d'info sur comment combiner NTLM et formulaires. Pour que la boîte de dialogue NTLM natif login/password ne soit jamais affichée-authentification transparente ou page de login à l'apparence agréable.

Comment devrait fonctionner? L'utilisateur doit-il se voir demander un nom d'utilisateur et un mot de passe? Est-ce que son identifiant actuel (nom d'utilisateur du domaine) peut être utilisé sans demander à entrer login et mot de passe?

mise à JOUR de ces, en enquêtant sur le même problème:

lorsque j'ai posé cette question, Je ne comprenais pas parfaitement comment fonctionne L'authentification NTLM. interne. Une chose importante à comprendre est que si le navigateur de l'utilisateur ne supporte pas NTLM correctement ou si le support NTLM est désactivé par user - server n'aura jamais la chance de contourner cela.

comment L'authentification Windows fonctionne:

  1. Client envoyer une requête HTTP régulière au serveur
  2. le serveur répond avec le statut HTTP 401 et l'indication que L'authentification NTLM doit être utilisée pour accéder aux ressources
  3. message de type NTLM envoyé par le Client
  4. le serveur répond avec le message NTLM Type2 avec challenge
  5. Client envoyer le message de Type3 avec la réponse au défi
  6. le Serveur répond avec le contenu réel demandé

comme vous le voyez, le navigateur qui ne supporte pas NTLM n'ira pas à l'étape (3), à la place l'Utilisateur sera montré page d'erreur 401 générée par IIS.

si l'utilisateur n'a pas de justificatifs d'identité, après annulation de la fenêtre de dialogue d'authentification NTLM le navigateur ne continuera pas à (3) comme bien.

nous n'avons donc aucune chance de rediriger automatiquement les utilisateurs vers la 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 oui, rediriger vers la page D'accueil protégée NTLM.

Et si non, afficher formulaire de connexion et d'autoriser l'authentification en saisissant manuellement les login et mot de passe.

la décision est habituellement prise en fonction de l'adresse IP et/ou du nom de l'hôte de l'utilisateur, soit en faisant correspondre les plages IP, soit en vérifiant tableau des IPs prédéfinis.

19
demandé sur AgentFire 2010-10-27 00:51:46

3 réponses

cet article pourrait vous faire pointer 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 des formulaires, L'autre utilise Windows. Celui qui utilise l'authentification Windows crée un cookie d'authentification de forme valide et redirige vers le second répertoire virtuel.

ASP.NET authentification en Mode mixte

8
répondu Pete Nelson 2017-08-07 13:41:40

j'ai cette configuration exacte en production, j'ai configuré mon portail pour utiliser FormsAuth et j'ai écrit une fonction qui prend L'IP des visiteurs pour chercher le compte utilisateur qui est connecté à cette IP / PC. En utilisant le nom que je trouve (par ex. 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 l'utilisateur IsApproved je crée un FormsAuthenticationTicket & cookie 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. Utilisateurs sans compte sur mon portail, 2. Quelques utilisateurs de MAC / Linux, 3. Les utilisateurs mobiles qui n'ont pas démarré sur le réseau et qui ont une politique de groupe activent leur pare-feu vers le haut).

La capture de cette solution est qu'elle nécessite imitation d'un compte administrateur de domaine pour interroger le PC de l'utilisateur, et que vous utilisez du code non géré netapi32.dll.

voici le code que j'utilise (la fonction externe n'appelle pas fournis, par souci de concision). J'ai essayé de simplifier un peu, depuis ont 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 que nous avons saisi dans la première fonction/processus, nous essayons de vérifier et de décider si nous devrions afficher un login ou auto-login 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 à ce sujet il y a longtemps, voici un lien vers le wrapper de netapi32.dll et mon aide D'Imitation que j'ai fourni dans le post Téléchargement Du Code Source

2
répondu Zachary 2014-12-06 16:20:49

vous ne pouvez pas avoir à la fois NTLM et FormsAuthentication dans le même ASP.NET application. Vous aurez besoin de deux applications différentes dans des répertoires virtuels séparés.

0
répondu Darin Dimitrov 2010-10-27 06:24:55