こいちゃんの趣味全開!!

クリエイターズネットワーク参加サイトのひとつ。趣味を書き綴ります。そこのあなた、お願い、ひかないでーっ。

/wwwroot/user-config.php

2012.12/4 by こいちゃん

ユーザーがパスワードを変更するためのページです。

<?php
require_once('login.php');
require_once('function.php');
$myself = './user-config.php';
?>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="./auth.css" media="screen,print" />
<link rel="stylesheet" type="text/css" href="./basic.css" media="screen,print" />
<title>パスワード変更</title>
</head>

<body>
<?php echo($Auth_data['script']); ?>
<div class="error">
<?php
$stmt = $db->prepare("SELECT password FROM auth WHERE username=:user");
$stmt->bindParam(':user', $Auth_data['username']);
$flag = $stmt->execute();
if (!$flag) {
	$info = $stmt->errorInfo();
	echo $info[2];
	echo "ユーザー名が正常に取得できませんでした。\n書き込みを強制的に終了しました。<br />\n";
	echo "<a href=\"./user-config.php\">戻る</a>";
	exit;
}
$oldpass = $stmt->fetch();
$oldpass = $oldpass[0];

#各フォームデータが空でないことを確認
if(isset($_POST['old-password'])) {
 if(isset($_POST['new-password'])) {
  if(isset($_POST['verify-password'])) {
#パスワードが正しいか確認、正しければ2つの新パスワードの値が同じか確認
	if($oldpass == $_POST['old-password']) {
	  if($_POST['new-password'] === $_POST['verify-password']) {
		$newpass = $_POST['new-password'];
	 	$passlen = strLen($newpass);
	 	if($passlen < 7 or $passlen > 32) {
	 		echo("Error: パスワードの長さが規定外です。<a href=\"./user-config.php\">戻る</a>");
	 		break;
	 	}
	 	if(preg_match('/[^a-zA-Z0-9_^|.]+/', $newpass)) {
	 		echo("Error: パスワードに使われている文字の一部が規定外です。<a href=\"./user-config.php\">戻る</a>");
	 		exit;
		}
		echo("</div><div class=\"comp\">\n");
		#パスワードデータ更新
		$stps = $db->prepare("UPDATE auth SET password=:newpass WHERE username=:user");
		$stps->bindParam(':newpass', $newpass);
		$stps->bindParam(':user', $Auth_data['username']);
		$flag = $stps->execute();
		if (!$flag) {
			$info = $stps->errorInfo();
			echo $info[2];
			echo "正常に新パスワードを書き込めませんでした。\n";
			exit;
		}
		
		#更新確認
		$flag = $stmt->execute();
		if (!$flag) {
			$info = $stmt->errorInfo();
			echo($info[2]);
			echo("ユーザー名が正常に取得できませんでした。\n更新を強制的に終了しました。<br />\n");
			echo("<a href=\"./user-config.php\">戻る</a>");
			exit();
		}
		$row = $stmt->fetch();
		
		if($row[0] == $newpass) {
			echo("パスワードの変更は正常に完了しました。\n");
		} elseif($row[0] == $oldpass) {
			echo("パスワードの変更ができませんでした。\n元のパスワードを使ってください。\n");
		} else {
			echo("パスワード変更時にエラーが発生しました。\n新・旧パスワードはどちらも使えません。管理者に連絡してください。\n");
		}
	  } else {
		echo("入力エラーです。再入力してください。\n");
	  }
	} else {
		echo("元のパスワードが間違っています。再入力してください。\n");
	}
    }
  }
}
?>
</div>
<h1>パスワード変更</h1>
パスワードを変更します。以下の入力欄全てに入力して下さい。
<table class="formtable"><form action="<?php echo($myself); ?>" method="POST" accept-charset="utf8">
	<tr><th>元のパスワード</th><td><input type="password" name="old-password" tabindex="1" size="50" /></td></tr>
	<tr><th>新しいパスワード</th><td><input type="password" name="new-password" tabindex="2" size="50" /></td></tr>
	<tr><th>新しいパスワード(確認)</th><td><input type="password" name="verify-password" tabindex="3" size="50" /></td></tr>
	<tr><th></th><td><input type="submit" class="submit" value="変更" tabindex="4" />
		<input type="reset" class="submit" value="リセット" tabindex="5" /></td></tr>
</form></table>
パスワード規定
<ul>
	<li>8文字以上32文字以下</li>
	<li>使える文字は以下の通り</li>
	<ul>
		<li>全て半角</li>
		<li>大文字・小文字アルファベット</li>
		<li>数字</li>
		<li>記号4種類(_^|.)</li>
	</ul>
</ul>
パスワードは管理者に筒抜けになります。ご注意ください。
<hr />
<a href="./index.php">トップへ</a>
</body></html>

1~18行目
他のスクリプトとほぼ同じため解説を省略させていただきます。

19~30行目
ログイン名を元に、データベースから現在のパスワードを取得、変数$oldpassに代入しています。
失敗した場合エラーメッセージを出力して強制終了。
データベースからの出力は配列変数になっているので、普通の変数に変換するために代入しなおしています。

33~39行目
フォームから送られてきたデータが入っているか検証し、値の確認をします。
データが入っていないフォームを特定し、エラーメッセージを変えるために5つのif文を使っています。
まず最初に「現在のパスワード」、「新しいパスワード」、「新しいパスワード再入力」の3つのフォームデータに値が格納されているかチェックします。次にデータベースから取得した現在のパスワードとフォームから送られてきたデータが同じものか確認し、最後に「新しいパスワード」と「新しいパスワード再入力」のデータが同じものか比較します。
すべてチェックをパスしたら、誤って元のデータを変更しないよう、変数$newpassに新しいパスワードを代入しておきます。

40~44行目
パスワードの長さをチェックします。ここではパスワードの長さを8文字以上32文字未満としています。
あまりにも短いとセキュリティが甘くなってしまいます。またデータベースに用意されている領域が32文字なので、それに合わせて最長の長さも設定しています。

45~48行目
パスワードに使われている文字種をチェックします。
データベースが誤作動を起こすとまずいので、ここでは半角英数字と4種類の記号のみ使えるように制限しています。
preg_matchは第1引数で指定された正規表現に第2引数の文字列が適合するかをチェックする関数です。
正規表現についてはこれだけで一つのページができてしまうので、よりまとめられている他のサイトをご覧ください。

51~60行目
データベースに保存されているパスワードを実際に書き換えます。
念のためステートメントを使ってSQLを実行しています。
ステートメントを保存する変数が$stpsと、いつも使っている$stmtと違うのは、この後で$stmtに保存されているSQLをもう一度実行するためです。これにより若干ですが無駄が減ります。

63~79行目
$stmtに保存されているSQLを再実行して、パスワードが正常に変更されているか確認します。
データベースから取得したデータが新しいパスワードと同じなら正常に処理が完了したことを、古いパスワードと同じなら変更ができなかったことを、どちらとも違ったらエラーが発生してしまったことを通知します。
念のため、新・旧どちらのパスワードとも違ったとしてもパスワードは表示させません。

80~88行目
最初のif文が成立しなかった場合のエラーメッセージです。

91~114行目
パスワード変更用のHTMLフォームです。
成否は関係なく、処理結果をフォームより後に表示させることで可読性を良くしています。(好みによりますが)

Tags: ,

Posted in PHPで動く掲示板プログラム |

Comments are closed.