質問: 'パスワードが違います'; show_login_form(); exit; } ```
回答: 「PHPによる簡単なログイン認証いろいろ」を参考にどうぞ.実装サンプルがあるので多分これだけでも答えになるかと思います. > > またname="username"に1文字だけ入れて実行しても”idが入力されていません” > > と出力されます。 > > > ちょっとこの点だけがコードの内容と整合性が取れていない気がするのですが,まず最初に直すべき点をあげると,kei344さんがすでに仰られている通り,`$admin_id`への代入を`$input_id`に直すことですね.global宣言が無意味になるのでおそらくミスです. その他,気になったことを挙げると * `$script`をaction属性の値に使っているが,もしここに`$_SERVER['PHP_SELF']`を使っている場合XSS脆弱性となるので絶対にやめること.`$_SERVER['SCRIPT_NAME']`を使っている場合はセーフだが,そもそもaction属性の値を空文字列にした場合は自分自身に対してPOSTすることになるので,これが一番いい. * エラーが発生するリスクがあるので,変数の存在確認に関してノーチェックで`$_POST['username']`などを参照しない.最低限`isset`での存在確認を行う.最善を求めるなら更に配列を弾くために文字列であるかどうかの検証も行う.この処理を`filter_input`を使うと1つにまとめることができる. 備考: $_GET, $_POSTなどを受け取る際の処理 * HTML出力以外の処理(ハッシュ生成など)を行うタイミングで`htmlspecialchars`の目的外使用をしない.これはテキストをHTMLとして埋め込む瞬間にのみ使うべき関数である.パスワードに「&」などの特殊文字が含まれていた場合,生成されるハッシュが誤ったものになってしまう. 備考: 「何故htmlspecialcharsを通すのか?」を一言でどうぞ * SHA512はハッシュ関数としては十分な強度があるが,ソルト無しで使うとレインボーテーブル攻撃に弱いという欠点があるので,必ずソルトを入れる.更にソルトを毎回ランダムにしてくれる`password_hash`関数やそれに対応した検証関数の`password_verify`を使うのが最もセキュリティが固くなるので,これを使うべき. 備考: PHPによる簡単なログイン認証いろいろ * ユーザ名までハッシュ化してしまうと利便性の面で大きなディスアドバンテージがあるので,パスワードのハッシュ化が強力であればそれだけで十分. 【追記】 直すならこんな感じでしょうか. はHTMLとしては誤っているのでついでに に直しておきます.また後から気づいたんですが,パスワードの方もハッシュ化が無意味になってる気がします. `$admin_password_sha`は最初から直接文字列で定義されているかと思いきや,平文の`$admin_password`から毎回生成されていますよね.**平文でパスワードをスクリプトに書いてはいけません.**それを避けるためにハッシュ関数があるんですから. ``` IDとパスワードを入力してください ID PW {$login_error_message} ``` ``` global $admin_id; // 平文 global $admin_password_hash; // password_hash関数で生成しておいたBlowfishハッシュ global $login_error_message; $input_id = (string)filter_input(INPUT_POST, 'username'); $input_password= (string)filter_input(INPUT_POST, 'password'); if ($admin_id === '') { $login_error_message = 'idが入力されていません'; show_login_form(); exit; } if ($input_password === '') { $login_error_message = 'パスワードが入力されていません'; show_login_form(); exit; } if (($admin_id !== $input_id) | !password_verify($input_password, $admin_password_hash)) { $login_error_message = 'IDまたはパスワードが違います'; show_login_form(); exit; } ``` こういうケースではIDもできれば隠蔽したいことでしょう.そのために「IDまたはパスワードが違います」というエラーメッセージでまとめたほうが望ましいです.また,`password_verify`を確実に実行しないと実行時間の差から「最低限IDが間違っている」ということは推測されますので,論理演算子の`||`ではなく短絡評価のないビット演算子の`|`を敢えて使っています.