認証を処理するためのバッチスクリプトを作成する際の問題は、誰かがバッチスクリプトを編集して単純にgoto program
を上部の近くに挿入することが容易だということです。あなたはほとんど利益のために自分のために多くの仕事を作り出しています。
上記のスクリプトが表示されないのは、:login
セクション内で、password.txtに格納されている値を読み取っていないことです。従って"%uname%"
は決して"%name%"
と等しくなりません。他にも欠けているものがたくさんあります。テキストファイルにプレーンテキストのパスワードを保存するのは危険です。
この道を続けることを強くお勧めする場合は、これを試してください。これは、ユーザー名で塩漬けされたBase64でコード化されたSHA512ハッシュとしてパスワードを格納します。こうすれば、あなたのプロジェクトは少なくとも危険ではありません(ユーザー名が攻撃者に知られていないと仮定して)。
<# : Batch portion
@echo off & setlocal disabledelayedexpansion
set "loginfile=%~dpn0.data"
if exist "%loginfile%" goto login
:registration
echo Welcome to %~nx0! Please register.
set /P "user=Username? "
call :passwordPrompt hash plain "%user%"
if defined user if defined hash (
>> "%loginfile%" echo(%hash%
goto main
)
goto registration
:login
echo Welcome to %~nx0! Please log in. Enter "new" to register a new account.
set /P "user=Username? "
if /I "%user%"=="new" goto registration
call :passwordPrompt hash plain "%user%"
find "%hash%" "%loginfile%" >NUL || (
echo Invalid credentials.
goto login
)
:main
rem // In case you need it, the entered password is stored in %plain%
echo Login successful. Enjoy the fruits of your labor.
wmic os get localdatetime /value
rem // end main runtime
goto :EOF
:passwordPrompt <return_hash> <return_plain> <username>
setlocal disabledelayedexpansion
set "user=%~3"
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0}|out-string)"') do set "%%I"
endlocal && set "%~1=%h%" && set "%~2=%p%" && exit /b
: end Batch/begin PowerShell hybrid code #>
$env:user = $env:user.toLower()
[console]::Error.Write("Password for $($env:user)? ")
$i = read-host -AsSecureString
$m = [Runtime.InteropServices.Marshal]
$p = $m::PtrToStringAuto($m::SecureStringToBSTR($i))
"h={0}" -f [Convert]::ToBase64String([Security.Cryptography.HashAlgorithm]::Create(`
'SHA512').ComputeHash([Text.Encoding]::UTF8.GetBytes("$($env:user)`n$p")))
"p=$p"
は、ここでコメントで注釈が付け同じスクリプトです。あなたが何かの詳細な説明をしたいのなら教えてください。
<# : Batch portion
@rem # The previous line does nothing in Batch, but begins a multiline comment block
@rem # in PowerShell. This allows a single script to be executed by both interpreters.
@echo off
rem # setlocal limits the scope of variables to this script.
rem # disabledelayedexpansion prevents exclamation marks from being mangled
setlocal disabledelayedexpansion
rem # set "loginfile=drive:\path\to\BatFileBaseName.data"
set "loginfile=%~dpn0.data"
if exist "%loginfile%" goto login
:registration
echo Welcome to %~nx0! Please register.
set /P "user=Username? "
rem # calls the :passwordPrompt function, which will set %hash% and %plain%
call :passwordPrompt hash plain "%user%"
if defined user if defined hash (
>> "%loginfile%" echo(%hash%
goto main
)
goto registration
:login
echo Welcome to %~nx0! Please log in. Enter "new" to register a new account.
set /P "user=Username? "
if /I "%user%"=="new" goto registration
rem # calls the :passwordPrompt function, which will set %hash% and %plain%
call :passwordPrompt hash plain "%user%"
rem # If hash doesn't exist in login file, then fail auth.
find "%hash%" "%loginfile%" >NUL || (
echo Invalid credentials.
goto login
)
:main
rem # In case you need it, the entered password is stored in %plain%
echo Login successful. Enjoy the fruits of your labor.
wmic os get localdatetime /value
rem # end main runtime
goto :EOF
rem # :passwordPrompt function
rem # The first two args are the names of empty vars to be populated with return values.
rem # The third arg is the username. It's not modified.
:passwordPrompt <return_hash> <return_plain> <username>
setlocal disabledelayedexpansion
set "user=%~3"
rem # Use "for /f" to capture the output of the powershell command. This powershell
rem # command executes the hybrid portion at the bottom of this script.
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0}|out-string)"') do set "%%I"
rem # To learn more about returning values from Batch functions, see this tutorial:
rem # http://www.dostips.com/DtTutoFunctions.php
endlocal && set "%~1=%h%" && set "%~2=%p%" && exit /b
rem # End multi-line PowerShell comment block. Begin PowerShell scripting.
: end Batch/begin PowerShell hybrid code #>
# Make username case-insensitive
$env:user = $env:user.toLower()
# Output to stderr to avoid being captured or silenced by for /f
[console]::Error.Write("Password for $($env:user)? ")
# Get user input. Hide keystrokes with stars. Store as a secure object
$secure = read-host -AsSecureString
# Marshal direct access to RAM
$marshal = [Runtime.InteropServices.Marshal]
# Get pointer to RAM location containing entered string
$PTR = $marshal::SecureStringToBSTR($secure)
# Retrieve contents of RAM at that pointer
$plain = $marshal::PtrToStringAuto($PTR)
# Convert salt + line feed + $plain to a byte array
$bytes = [Text.Encoding]::UTF8.GetBytes("$($env:user)`n$plain")
# Create SHA512 hash algorithm
$SHA512 = [Security.Cryptography.HashAlgorithm]::Create('SHA512')
# Compute hash
$hash = $SHA512.ComputeHash($bytes)
# Convert hash to Base64
$b64 = [Convert]::ToBase64String($hash)
# Output results
"h=$b64"
"p=$plain"
非常に良いコード!私はちょうどそれをテストしたし、私はパワーシェル関数を使用するのが好きです。私はあなたのコードにいくつかのコメントを追加する時間がある場合、あなたから新しいものを学んでいます!もう一度ありがとう;) – Hackoo
@ハッコウ書くのは難しかったので、読むのも難しいはずです。 (私は冗談です)特に注釈を付ける部分はありますか?あなたが興味を持っているバッチ+ PowerShell多言語形式の場合、[this forum thread](http://www.dostips.com/forum/viewtopic.php?f=3&t=5526)には異なる例があります。 – rojo
あなたのコードはうまくいき、あなたの努力に感謝しますが、コードをもっとシンプルにする方法はありますか?私の友人は、例えば "echo << C:\ Program"というコマンドで、txtやdllファイルを読み込むことができると私に言った。あなたのコードを理解し始めていない。 : 'D – miragetv7