Authentification basée sur les formulaires PHP sous Windows à l'aide de comptes d'utilisateurs locaux

StackOverflow https://stackoverflow.com/questions/60585

Question

J'utilise PHP, Apache et Windows.Je n'ai pas de configuration de domaine, j'aimerais donc que l'authentification basée sur les formulaires de mon site Web utilise la base de données de comptes d'utilisateurs locale intégrée à Windows (je pense qu'elle s'appelle SAM).

Je sais que si Active Directory est configuré, vous pouvez utiliser le module PHP LDAP pour vous connecter et vous authentifier dans votre script, mais sans AD, il n'y a pas de LDAP.Quel est l'équivalent pour les machines autonomes ?

Était-ce utile?

La solution

Je n'ai pas non plus trouvé de solution simple.Il existe des exemples utilisant CreateObject et le fournisseur WinNT ADSI.Mais finalement ils se heurtent tous Problèmes d’authentification des utilisateurs avec le fournisseur WinNT des interfaces de service Active Directory.Je ne suis pas sûr à 100% mais je deviner l'approche WSH/network connect a le même problème.
Selon Comment valider les informations d'identification des utilisateurs sur les systèmes d'exploitation Microsoft vous devez utiliser LogonUser ou SSPI.
Il dit aussi

LogonUser Win32 API does not require TCB privilege in Microsoft Windows Server 2003, however, for downlevel compatibility, this is still the best approach.

Sous Windows XP, il n'est plus nécessaire qu'un processus dispose du privilège SE_TCB_NAME pour appeler LogonUser.Par conséquent, la méthode la plus simple pour valider les informations d’identification d’un utilisateur sous Windows XP consiste à appeler l’API LogonUser.

Par conséquent, si j'étais certain que la prise en charge de Win9x/2000 n'est pas nécessaire, j'écrirais une extension qui expose LogonUser à php.
Vous pourriez aussi être intéressé par Authentification utilisateur à partir de comptes NT.Il utilise l'extension w32api et nécessite une DLL de support... Je préfère écrire cette petite extension LogonUser ;-)
Si ce n'est pas faisable, j'examinerais probablement le module fastcgi pour IIS et sa stabilité et laisserais IIS gérer l'authentification.

modifier:
J'ai également essayé d'utiliser System.Security.Principal.WindowsIdentity et php extension com/.net.Mais le constructeur dotnet ne semble pas permettre de transmettre des paramètres au constructeur d'objets et mon "expérience" pour obtenir l'assembly (et avec lui CreateInstance()) à partir de GetType() a échoué avec une erreur "zval inconnu".

Autres conseils

Bonne question!

J'y ai réfléchi un peu...et je ne trouve pas de bonne solution.Ce à quoi je peux penser, c'est un horrible hack horrible qui pourrait bien fonctionner.Après avoir constaté que personne n'avait posté de réponse à cette question depuis près d'une journée, j'ai pensé qu'une réponse mauvaise, mais efficace, serait acceptable.

Le fichier SAM est interdit pendant que le système est en cours d'exécution.Il existe quelques astuces d'injection de DLL que vous pourrez peut-être utiliser, mais à la fin, vous vous retrouverez simplement avec des hachages de mot de passe et vous devrez de toute façon hacher les mots de passe fournis par l'utilisateur pour les comparer.

Ce que vous voulez vraiment, c'est quelque chose qui tente d'authentifier l'utilisateur par rapport au fichier SAM.Je pense que vous pouvez le faire en faisant quelque chose comme ce qui suit.

  1. Créez un partage de fichiers sur le serveur et faites en sorte que seuls les comptes sous lesquels vous souhaitez pouvoir vous connecter y aient accès.
  2. En PHP, utilisez la commande système pour appeler un script wsh qui :monte le partage en utilisant le nom d'utilisateur et le mot de passe fournis par l'utilisateur du site Web.enregistre si cela fonctionne, puis démonte le lecteur si c'est le cas.
  3. Collectez le résultat d'une manière ou d'une autre.Le résultat peut être renvoyé à php soit sur la sortie standard du script, soit, espérons-le, en utilisant le code de retour du script.

Je sais que ce n'est pas joli, mais ça devrait marcher.

Je me sens sale :|

Modifier:la raison pour laquelle vous invoquez le script wsh externe est que PHP ne vous permet pas d'utiliser des chemins UNC (pour autant que je me souvienne).

Construire une extension PHP nécessite un investissement assez important en termes d’espace disque.Comme j'ai déjà installé l'environnement GCC (MinGW), j'ai décidé de profiter des performances en lançant un processus à partir du script PHP.Le code source est ci-dessous.

// Usage: logonuser.exe /user username /password password [/domain domain]
// Exit code is 0 on logon success and 1 on failure.

#include <windows.h>

int main(int argc, char *argv[]) {
    HANDLE r = 0;
    char *user = 0;
    char *password = 0;
    char *domain = 0;
    int i;

    for(i = 1; i < argc; i++) {
        if(!strcmp(argv[i], "/user")) {
            if(i + 1 < argc) {
                user = argv[i + 1];
                i++;
            }
        } else if(!strcmp(argv[i], "/domain")) {
            if(i + 1 < argc) {
                domain = argv[i + 1];
                i++;
            }
        } else if(!strcmp(argv[i], "/password")) {
            if(i + 1 < argc) {
                password = argv[i + 1];
                i++;
            }
        }
    }

    if(user && password) {
        LogonUser(user, domain, password, LOGON32_LOGON_BATCH, LOGON32_PROVIDER_DEFAULT, &r);
    }
    return r ? 0 : 1;
}

Voici ensuite la source PHP démontrant son utilisation.

if($_SERVER['REQUEST_METHOD'] == 'POST') {
    if(isset($_REQUEST['user'], $_REQUEST['password'], $_REQUEST['domain'])) {
        $failure = 1;
        $user = $_REQUEST['user'];
        $password = $_REQUEST['password'];
        $domain = $_REQUEST['domain'];

        if($user && $password) {
            $cmd = "logonuser.exe /user " . escapeshellarg($user) . " /password " . escapeshellarg($password);
            if($domain) $cmd .= " /domain " . escapeshellarg($domain);
            system($cmd, $failure);
        }

        if($failure) {
            echo("Incorrect credentials.");
        } else {
            echo("Correct credentials!");
        }
    }
}
?>
<form action="<?php echo(htmlentities($_SERVER['PHP_SELF'])); ?>" method="post">
    Username: <input type="text" name="user" value="<?php echo(htmlentities($user)); ?>" /><br />
    Password: <input type="password" name="password" value="" /><br />
    Domain: <input type="text" name="domain" value="<?php echo(htmlentities($domain)); ?>" /><br />
    <input type="submit" value="logon" />
</form>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top