удалить Запрос пароля командной строки в PHP




удалить html теги php (8)

Я пишу инструмент командной строки, чтобы помочь моему веб-приложению. Для подключения к службе требуется пароль. Я хотел бы, чтобы сценарий показывал приглашение пароля, поэтому мне не нужно передавать его в качестве аргумента командной строки.

Это достаточно просто, но я бы хотел, чтобы он не повторял пароль на экране, когда он был напечатан. Как я могу это сделать с PHP?

Бонусные баллы за это делают в чистом PHP (без system('stty') ) и заменяют символы * .

РЕДАКТИРОВАТЬ:

Скрипт будет работать в системе unix (linux или mac). Сценарий написан на PHP, и, скорее всего, останется таким.

Кроме того, для записи, stty способ сделать это:

echo "Password: ";
system('stty -echo');
$password = trim(fgets(STDIN));
system('stty echo');
// add a new line since the users CR didn't echo
echo "\n";

Я бы предпочел, чтобы там не было вызовов system() .


Я переформатировал JMW решение JMW чтобы вы могли просто вырезать и вставить его в существующий PHP-код.

function getPassword()
{
  $pwd=shell_exec('C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -Command "$Password=Read-Host -assecurestring \"Please enter your password\" ; $PlainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)) ; echo $PlainPassword;"');
  $pwd=explode("\n", $pwd); $pwd=$pwd[0];
  return $pwd;
}

Чтобы использовать его:

$usersPassword=getPassword();

Я нахожусь в Powershell V5.0, но путь к каталогу по-прежнему отображается как v1.0, поэтому строка с кавычками в вызове shell_exec должна быть в порядке.


Принятый ответ недостаточно хорош. Прежде всего, решение Windows не работает в Windows 7 и выше. Решение для других ОС зависит от Bash и bash встроенного «чтения». Однако существуют системы, которые не используют Bash (например, OpenBSD), и это явно не сработает.

В этом blog я обсуждал решение, которое работает практически с любой ОС на базе Unix и Windows с 95 до 8. В решении Windows используется внешняя программа, написанная на C поверх Win32 API. Решение для других ОС использует внешнюю команду 'stty'. Мне еще предстоит увидеть систему на основе Unix, которая не имеет «stty»,


Вы можете использовать мой файл github.com/Seldaek/hidden-input для получения реального скрытого ввода без утечки информации в любом месте экрана.

<?php

echo 'Enter password: ';
$password = exec('hiddeninput.exe');
echo PHP_EOL;

echo 'Password was: ' . $password . PHP_EOL;

Если вы удалите последнее эхо, пароль никогда не появится, но вы можете использовать его для проверки obvoiusly.


Это самое простое решение для всех платформ:

function prompt($message = 'prompt: ', $hidden = false) {
    if (PHP_SAPI !== 'cli') {
        return false;
    }
    echo $message;
    $ret = 
        $hidden
        ? exec(
            PHP_OS === 'WINNT' || PHP_OS === 'WIN32'
            ? __DIR__ . '\prompt_win.bat'
            : 'read -s PW; echo $PW'
        )
        : rtrim(fgets(STDIN), PHP_EOL)
    ;
    if ($hidden) {
        echo PHP_EOL;
    }
    return $ret;
}

Затем создайте prompt_win.bat в том же каталоге:

SetLocal DisableDelayedExpansion
Set "Line="
For /F %%# In ('"Prompt;$H & For %%# in (1) Do Rem"') Do (
    Set "BS=%%#"
)

:loop_start
    Set "Key="
    For /F "delims=" %%# In ('Xcopy /L /W "%~f0" "%~f0" 2^>Nul') Do (
        If Not Defined Key (
            Set "Key=%%#"
        )
    )
    Set "Key=%Key:~-1%"
    SetLocal EnableDelayedExpansion
    If Not Defined Key (
        Goto :loop_end
    )
    If %BS%==^%Key% (
        Set "Key="
        If Defined Line (
            Set "Line=!Line:~0,-1!"
        )
    )
    If Not Defined Line (
        EndLocal
        Set "Line=%Key%"
    ) Else (
        For /F "delims=" %%# In ("!Line!") Do (
            EndLocal
            Set "Line=%%#%Key%"
        )
    )
    Goto :loop_start
:loop_end

Echo;!Line!

Найдено на сайте.

function prompt_silent($prompt = "Enter Password:") {
  if (preg_match('/^win/i', PHP_OS)) {
    $vbscript = sys_get_temp_dir() . 'prompt_password.vbs';
    file_put_contents(
      $vbscript, 'wscript.echo(InputBox("'
      . addslashes($prompt)
      . '", "", "password here"))');
    $command = "cscript //nologo " . escapeshellarg($vbscript);
    $password = rtrim(shell_exec($command));
    unlink($vbscript);
    return $password;
  } else {
    $command = "/usr/bin/env bash -c 'echo OK'";
    if (rtrim(shell_exec($command)) !== 'OK') {
      trigger_error("Can't invoke bash");
      return;
    }
    $command = "/usr/bin/env bash -c 'read -s -p \""
      . addslashes($prompt)
      . "\" mypassword && echo \$mypassword'";
    $password = rtrim(shell_exec($command));
    echo "\n";
    return $password;
  }
}

Почему бы не использовать SSH-соединение? Вы можете абстрагировать команды, перенаправить ввод / вывод и получить полный контроль.

Вы можете предоставить кому-то чистую чистую оболочку с минимальными правами, а также пароль, который будет POST'ed вместе с SSH2 :: Connect (), чтобы открыть оболочку.

Я создал хороший класс для работы с расширением php SSH2, возможно, это поможет вам; (и он также обеспечивает безопасную передачу файлов)

<?php

/**
 * SSH2
 * 
 * @package Pork
 * @author SchizoDuckie
 * @version 1.0
 * @access public
 */
class SSH2
{
    private $host;
    private $port;
    private $connection;
    private $timeout;
    private $debugMode;
    private $debugPointer;
    public $connected; 
    public $error;


    /**
     * SSH2::__construct()
     * 
     * @param mixed $host
     * @param integer $port
     * @param integer $timeout
     * @return
     */
    function __construct($host, $port=22, $timeout=10)
    {
        $this->host = $host;
        $this->port = $port;
        $this->timeout = 10;
        $this->error = 'not connected';
        $this->connection = false;
        $this->debugMode = Settings::Load()->->get('Debug', 'Debugmode');
        $this->debugPointer = ($this->debugMode) ? fopen('./logs/'.date('Y-m-d--H-i-s').'.log', 'w+') : false;
        $this->connected = false;

    }


    /**
     * SSH2::connect()
     * 
     * @param mixed $username
     * @param mixed $password
     * @return
     */
    function connect($username, $password)
    {
        $this->connection = ssh2_connect($this->host, $this->port);
        if (!$this->connection) return $this->error("Could not connect to {$this->host}:{$this->port}");
        $this->debug("Connected to {$this->host}:{$this->port}");
        $authenticated = ssh2_auth_password($this->connection, $username, $password);
        if(!$authenticated) return $this->error("Could not authenticate: {$username}, check your password");
        $this->debug("Authenticated successfully as {$username}");
        $this->connected = true;

        return true;
    }

    /**
     * SSH2::exec()
     *
     * @param mixed $command shell command to execute
     * @param bool $onAvailableFunction a function to handle any available data.
     * @param bool $blocking blocking or non-blocking mode. This 'hangs' php execution until the command has completed if you set it to true. If you just want to start an import and go on, use this icm onAvailableFunction and false
     * @return
     */
    function exec($command, $onAvailableFunction=false, $blocking=true)
    {
        $output = '';
        $stream = ssh2_exec($this->connection, $command);
        $this->debug("Exec: {$command}");
        if($onAvailableFunction !== false)
        {
            $lastReceived = time();
            $timeout =false;
            while (!feof($stream) && !$timeout)
            {
                $input = fgets($stream, 1024);
                if(strlen($input) >0)
                {
                    call_user_func($onAvailableFunction, $input);
                    $this->debug($input);
                    $lastReceived = time();
                }
                else
                {
                    if(time() - $lastReceived >= $this->timeout)
                    {
                        $timeout = true;
                        $this->error('Connection timed out');
                        return($this->error);
                    }
                }
            }
        }
        if($blocking === true && $onAvailableFunction === false)
        {
            stream_set_blocking($stream, true);
            $output = stream_get_contents($stream);
            $this->debug($output);
        }
        fclose($stream);
        return($output);
    }


    /**
     * SSH2::createDirectory()
     *
     * Creates a directory via sftp
     *
     * @param string $dirname
     * @return boolean success
     *  
     */
    function createDirectory($dirname)
    {
        $ftpconnection = ssh2_sftp ($this->connection);
        $dircreated = ssh2_sftp_mkdir($ftpconnection, $dirname, true);
        if(!$dircreated) 
        {
            $this->debug("Directory not created: ".$dirname);
        }
        return $dircreated;
    }

    public function listFiles($dirname)
    {
        $input = $this->exec(escapeshellcmd("ls  {$dirname}"));
        return(explode("\n", trim($input)));

    }

    public function sendFile($filename, $remotename)
    {
        $this->debug("sending {$filename} to {$remotename} ");
        if(file_exists($filename) && is_readable($filename))
        {
            $result = ssh2_scp_send($this->connection, $filename, $remotename, 0664);
        }
        else
        {
            $this->debug("Unable to read file : ".$filename);
            return false;
        }
        if(!$result) $this->debug("Failure uploading {$filename} to {$remotename}");
        return $result;
    }

    public function getFile($remotename, $localfile)
    {
        $this->debug("grabbing {$remotename} to {$localfile}");
        $result = ssh2_scp_recv($this->connection, $remotename, $localfile);

        if(!$result) $this->debug("Failure downloading {$remotename} to {$localfile}");
        return $result;
    }

    /**
     * SSH2::debug()
     * 
     * @param mixed $message
     * @return
     */
    function debug($message) 
    {
        if($this->debugMode)
        {
            fwrite($this->debugPointer, date('Y-m-d H:i:s')." : ".$message."\n");
        }
    }



    /**
     * SSH2::error()
     * 
     * @param mixed $errorMsg
     * @return
     */
    function error($errorMsg) 
    {
        $this->error = $errorMsg;
        $this->debug($errorMsg);
        return false;
    }   

    /**
     * SSH2::__destruct()
     * 
     * @return
     */
    function __destruct() 
    {
        if($this->connection){
            $this->connection = null;
        }
        if($this->debugMode && $this->debugPointer)
        {
            fclose($this->debugPointer);
        }
    }       


}

Пример использования:

$settings = Settings::Load()->Get("SecureServer");
$ssh = new SSH2($settings['host']);
if( $ssh->connect($settings['username'], $settings['password']))
{
    echo $ssh->exec("ls -la ".$settings['path'], false, true);  
    flush();    
}

Я предполагаю, что нет простого способа сделать это (на самом деле я никак не могу придумать) без использования stty -echo. Если вы намереваетесь запустить его на окнах, вы можете создать пакетный скрипт, который предоставит неименованную введенную информацию вашему скрипту php.

@echo off
cls
SET /P uname=Enter Username:
echo hP1X500P[PZBBBfh#b##[email protected]`$fPf]f3/f1/5++u5>in.com
set /p password=Enter password :<nul
for /f “tokens=*” %%i in (’in.com’) do set password=%%i
del in.com
echo.
c:\php\php.exe d:\php\test.php %uname% “%password%”
Pause

пример из http://www.indiangnu.org/2008/php-hide-user-input-using-batch-script-windows/


В зависимости от вашей среды (т. ncurses_noecho() Не в Windows) вы можете использовать библиотеку ncurses (в частности, ncurses_noecho() чтобы остановить клавиатурное эхо и ncurses_getch() для чтения ввода), чтобы получить пароль, не отображая его на экране.







passwords