PHP의 명령 줄 암호 프롬프트
웹 앱을 지원하는 명령 줄 도구를 작성 중입니다. 서비스에 연결하려면 비밀번호가 필요합니다. 스크립트가 암호 프롬프트를 표시하여 명령 줄 인수로 전달할 필요가 없도록하고 싶습니다.
간단하지만 입력 한 암호를 화면에 표시하지 않기를 바랍니다. PHP로 어떻게 할 수 있습니까?
순수 PHP에서 수행하고 (아니오 system('stty')
) 문자를 *
.
편집하다:
스크립트는 시스템 (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()
거기에 전화를 걸지 않는 편이 낫다 .
sitepoint 에서 찾았습니다 .
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;
}
}
환경 (즉, Windows가 아님)에 따라 ncurses 라이브러리 (특히 ncurses_noecho () 함수를 사용하여 키보드 에코를 중지하고 ncurses_getch () 를 사용하여 입력을 읽음) 화면에 표시하지 않고 암호를 가져올 수 있습니다.
내 hiddeninput.exe 파일을 사용 하여 화면 어디에도 정보를 유출하지 않고 실제 숨겨진 입력을 얻을 수 있습니다.
<?php
echo 'Enter password: ';
$password = exec('hiddeninput.exe');
echo PHP_EOL;
echo 'Password was: ' . $password . PHP_EOL;
마지막 에코를 제거하는 경우 암호가 표시되지 않아야하지만 확인을 위해 분명하게 사용할 수 있습니다.
이것은 모든 플랫폼에서 가장 쉬운 솔루션입니다.
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!
stty -echo를 사용하지 않고는 간단한 방법이 없다고 생각합니다 (실제로는 어떤 방법도 생각할 수 없습니다). Windows에서 실행하려는 경우 PHP 스크립트에 선택되지 않은 유형 정보를 제공하는 배치 스크립트를 만들 수 있습니다.
@echo off
cls
SET /P uname=Enter Username:
echo hP1X500P[PZBBBfh#b##fXf-V@`$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/ 에서 가져온 예
powershell을 지원하는 모든 Windows 시스템에서 작동합니다. (출처 : http://www.qxs.ch/2013/02/08/php-cli-password-prompts-on-windows-7/ )
<?php
// please set the path to your powershell, here it is: C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe
$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];
echo "You have entered the following password: $pwd\n";
아래 방법은 Linux CLI에서는 작동하지만 Windows CLI 또는 Apache에서는 작동하지 않습니다. 또한 표준 Ascii 테이블의 문자로만 작동합니다 (확장 문자 세트와 호환되도록 만드는 데 많은 시간이 걸리지 않습니다).
암호 복사 및 붙여 넣기로부터 보호하기 위해 약간의 코드를 입력했습니다. 두 주석 사이의 비트가 제거되면 암호를 삽입 / 붙여 넣을 수 있습니다.
누군가에게 도움이되기를 바랍니다.
<?php
echo("Password: ");
$strPassword=getObscuredText();
echo("\n");
echo("You entered: ".$strPassword."\n");
function getObscuredText($strMaskChar='*')
{
if(!is_string($strMaskChar) || $strMaskChar=='')
{
$strMaskChar='*';
}
$strMaskChar=substr($strMaskChar,0,1);
readline_callback_handler_install('', function(){});
$strObscured='';
while(true)
{
$strChar = stream_get_contents(STDIN, 1);
$intCount=0;
// Protect against copy and paste passwords
// Comment \/\/\/ to remove password injection protection
$arrRead = array(STDIN);
$arrWrite = NULL;
$arrExcept = NULL;
while (stream_select($arrRead, $arrWrite, $arrExcept, 0,0) && in_array(STDIN, $arrRead))
{
stream_get_contents(STDIN, 1);
$intCount++;
}
// /\/\/\
// End of protection against copy and paste passwords
if($strChar===chr(10))
{
break;
}
if ($intCount===0)
{
if(ord($strChar)===127)
{
if(strlen($strObscured)>0)
{
$strObscured=substr($strObscured,0,strlen($strObscured)-1);
echo(chr(27).chr(91)."D"." ".chr(27).chr(91)."D");
}
}
elseif ($strChar>=' ')
{
$strObscured.=$strChar;
echo($strMaskChar);
//echo(ord($strChar));
}
}
}
readline_callback_handler_remove();
return($strObscured);
}
?>
SSH 연결을 사용하지 않는 이유는 무엇입니까? 명령을 추상화하고 입력 / 출력을 리디렉션하고 모든 권한을 가질 수 있습니다.
필요한만큼의 권한이없는 순수한 셸을 누군가에게 제공하고 셸을 열기 위해 SSH2 :: Connect ()와 함께 암호를 POST하도록 할 수 있습니다.
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();
}
이론적으로 stream_set_blocking ()을 사용하여 할 수 있지만 STDIN을 관리하는 PHP 버그가있는 것 같습니다.
보기 : http://bugs.php.net/bug.php?id=34972 http://bugs.php.net/bug.php?id=36030
직접 시도해보십시오.
echo "Enter Password: ";
$stdin = fopen('php://stdin','r');
// Trying to disable stream blocking
stream_set_blocking($stdin, FALSE) or die ('Failed to disable stdin blocking');
// Trying to set stream timeout to 1sec
stream_set_timeout ($stdin, 1) or die ('Failed to enable stdin timeout');
The accepted answer is not good enough. First of all, the Windows solution doesn't work on Windows 7 and above. The solution for other OSs depends on Bash and bash built-in 'read'. However, there are systems which does not use Bash (eg. OpenBSD) and where this obviously won't work.
In this blog I've discussed solution which works on almost any Unix based OS and Windows from 95 to 8. The Windows solution uses external program written in C on top Win32 API. The solution for other OSs uses external command 'stty'. I have yet to see a Unix based system which does not have 'stty'
참고URL : https://stackoverflow.com/questions/187736/command-line-password-prompt-in-php
'Program Tip' 카테고리의 다른 글
jsFiddle로 두 개 이상의 프레임 워크를 선택하려면 어떻게해야합니까? (0) | 2020.11.02 |
---|---|
SVG에서 텍스트 정렬 (0) | 2020.11.02 |
dotnetopenauth를 사용하는 Facebook / Twitter? (0) | 2020.11.02 |
2 단계 조회-설명 필요 (0) | 2020.11.02 |
언제 @classmethod를 사용해야하고 언제 def method (self)를 사용해야합니까? (0) | 2020.11.02 |