Чтение паролей

Задача
Необходимо прочитать информацию из командной строки, не отображая при этом сам ввод (например, при вводе паролей).

Решение
В системах UNIX отображение вводимых символов достигается применением /bin/stty:

// выключаем эхо
`/bin/stty -echo`;
// читаем пароль
$password = readline();
// снова включаем эхо
`/bin/stty echo`;

В Windows применяется функция w32api_register_function() – для импортирования функции _getch() из msvcrt.dll:

// загружаем расширение w32api и регистрируем функцию _getch()
dl('php_w32api.dll');
w32api_register_function('msvcrt.dll','_getch','int');
while(true) {
// получаем символ с клавиатуры
$c = chr(_getch());
if ( "\r" == $c || "\n" == $c ) {
// если это символ новой строки, прерываем цикл,
// мы получили наш пароль
break;
} elseif ("\x08" == $c) {
/* если это символ забоя, удалите предыдущий символ
из переменной $password */
$password = substr_replace($password,'',-1,1);
} elseif ("\x03" == $c) {
// если это Control-C, очищаем переменную $password и выходим из цикла
$password = NULL;
break;
} else {
// в противном случае добавляем символ к паролю
$password .= $c;
}
}

Обсуждение
В UNIX для управления характеристиками терминала применяется /bin/stty, предотвращающая отображение введенных символов на экране во время чтения пароля.


В Windows нет /bin/stty, поэтому для получения доступа к функции _getch() из динамической C-библиотеки Microsoft msvcrt.dll применяется расширение W32api. Функция _getch() читает символ, не отображая его на экране. Она возвращает ASCII-код прочитанного символа, поэтому его надо конвертировать в символьную строку с помощью функции chr(). Затем предпринимаются действия в зависимости от типа напечатанного символа. Если это символ новой строки или возврата каретки, то выходите из цикла, т. к. пароль уже введен. Если это символ забоя (backspace), то удаляете последний символ пароля. Если это символ прерывания , то вы устанавливаете пароль в NULL и выходите из цикла. Если ни одно из этих условий не выполняется, то символ добавляется к переменной $password. После выхода из цикла переменная $password содержит введенный пароль.

Следующая программа показывает приглашения Login: и Password: и сравнивает введенный пароль с соответствующим зашифрованным паролем, хранящимся в /etc/passwd. При этом необходимо, чтобы в системе не использовались теневые пароли.

print "Login: ";
$fh = fopen('php://stdin','r') or die($php_errormsg);
$username = rtrim(fgets($fh,64)) or die($php_errormsg);
preg_match('/^[a-zA-Z0-9]+$/',$username)
or die("Invalid username: only letters and numbers allowed");
print 'Password: ';
`/bin/stty -echo`;
$password = rtrim(fgets($fh,64)) or die($php_errormsg);
`/bin/stty echo`;
print "\n";
// больше нечего читать с клавиатуры
fclose($fh);
// находим соответствующую строку в /etc/passwd
$fh = fopen('/etc/passwd','r') or die($php_errormsg);
$found_user = 0;
while (! ($found_user || feof($fh))) {
$passwd_line = fgets($fh,256);
if (preg_match("/^$username:/",$passwd_line)) {
$found_user = 1;
}
}
fclose($fh);
$found_user or die ("Can't find user \"$username\"");
// анализируем корректную строку из /etc/passwd
$passwd_parts = split(':',$passwd_line);
/* кодируем введенный пароль и сравниваем его с паролем в
/etc/passwd */
$encrypted_password = crypt($password,
substr($passwd_parts[1],0,CRYPT_SALT_LENGTH));
if ($encrypted_password == $passwd_parts[1]) {
print "login successful";
} else {
print "login unsuccessful";
}.



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Анализ аргументов программы
Анализ аргументов программы с помощью getopt
Показ в окне графических элементов управления
Показ в окне нескольких графических элементов управления
Показ меню

Вернуться в раздел: PHP / 20. PHP на стороне клиента