#08 エラーチェックをしてみよう
http://dotinstall.com/lessons/poll_php_v2/9708
を参考に
投票された内容をチェックしてエラーが発生した場合の処理を実装
まず、トークンが入っていて
セッションの中のものと同じかチェックする
if(empty($_SESSION[‘token’] || $_POST[‘token’] != $_SESSION[‘token’]){
で判定できる
empty($_SESSION[‘token’]
は token が空という意味
$_POST[‘token’] != $_SESSION[‘token’])
は、token とおくられてきた token が違うなら
という意味
||はもしくは、というOR判定
これで、どちらかの条件にあてはまるものを検出できる
もし、該当するなら
echo “不正な操作です”;
exit;
で終了する
続いて、エラーチェック
回答は1~4なので
if(!in_array($_POST[‘answer’],array(1.2.3.4)){
で判定する
in_array() は
配列に指定した値があるか検索する
http://php.quus.net/array/in_array.php
を参考
今回なら
answer の値が1~4の間に入っているか調べている
!がついているので、条件式としては
入っていないなら、という意味になっている
この場合、エラーを出すように
$err =”写真を選択してください”;
とする
このままではエラーがでないので、HTML部分にソースを追記
body タグの下あたりに
<?php if(!empty($err)): ?>
<p style=”color:red”><?php echo h($err); ?></p>
<?php endif; ?>
と追記する
if(!empty($err)):
は$err に値が入っている場合、
つまりエラーがある場合という意味
で
この場合
<?php echo h($err); ?>
でエラーを表示している
カテゴリー: PHP + MySQL
CSRF対策の実施
CSRF対策の実施
#07 CSRF対策を施そう
http://dotinstall.com/lessons/poll_php_v2/9707
を参考に
セキュリティを高めるためにCSRF対策を施す
sha1はハッシュで、暗号化とは異なり求み戻せない
暗号化の場合は、鍵があれば元に戻せる
今回、編集するファイルは index.php
まず、投稿されたかどうか判定する
if($_SERVER[‘REQUEST_METHOD’] != ‘POST’)
!= ‘POST’はPOSTではない
つまり投稿されていない状態という意味
else のほうに、投稿されたときの処理を書く
投稿前の処理で、CSRF対策をしておく
CSRF対策は、トークンをフォームにセットして
投稿された後に、このフォームから投稿されたものか
値をチェックすることで判定する
これは、偽者のフォームなど、悪意あるフォームからの投稿を防ぐため
まず、セッションをみて
トークンがセットされていないなら、トークンをセットする
if(!isset($_SESSION[‘token’])){
とすれば判定できる
isset() は指定した値が入っているかチェックする
http://php.net/manual/ja/function.isset.php
を参考
トークンの中身は推測されにくいランダムな文字列を使う
このときに sha1() を使う
暗号化した文字列を取得するのに使う
http://phpjp.com/sha1.htm
を参考に
この中で mt_rand() という乱数を発生させる関数
これについては
乱数を生成する(rand, mt_rand)
http://www.phpbook.jp/func/math/index1.html
を参考
そして
uniqid()
これは
マイクロ秒単位の現在時刻にもとづいた、接頭辞つきの一意な ID を取得
一意というのは、他と被らないただ1つという意味
uniqid() で true が設定されていると
23文字になる
これについては
http://phpspot.net/php/man/php/function.uniqid.html
を参考
これらを元に
$_SESSION[‘token’] = sha1(uniqid(mt_rand(),true));
これでハッシュ化されたランダムな文字列を作り
token に設定している
また、セッションを使うため
require_one() の下あたりに
session_start();
を追記する
ここからセッション開始になる
また、HTMLのフォーム部分に
セッショントークンを埋め込むため
<input type=”hidden” name=”token” value=”<?php echo h($_SESSION[‘token’]); ?>”>
というように
type=”hidden” にして画面には表示されないようにして
おく
実行後、ブラウザでソースをみると、値がセットされているのがわかる
投票結果を jQuery で取得
#06 投票結果を取得してみよう
http://dotinstall.com/lessons/poll_php_v2/9706
を参考に
クリックされた画像のIDを取得するための処理をjQueryで実装
編集するのは index.php
の form タグの下あたりに
script タグで作成する
$(function(){
$(‘.candidate’).click(function(){
$(‘#answer’).val($(this).data(‘id’));
});
});
という処理になる
jQuery関連を勉強するとわかるけど
.candidate は
class=”candidate”
#answer は
id=”answer”
という意味
this はそのもの、というような意味
とりあえず、実働実験するので
input type=”hidden” だと見えないので
input type=”text” として値が取得できているか確認する
このままだと、写真をクリックしたときに
どれを選択したかわからないから
新しいクラスをつける
まず、CSSを設定する
head タグの中に
<style>
.selected {
border:4px solid red;
}
</style>
これで、選択した画像の回りに赤い線がでるようになる
この動作を jQuery で制御する
まず、すべての selected を外す
$(‘.candidate’).removeClass(‘selected’);
そして、選択したものに selected を追加する
$(this).addClass(‘selected’);
これで、再度読み込んでみると
選択した写真の回りに赤い線がでるようになり
わかりやすくなる
ここまでできたら、
<input type=”text” id=”answer” name=”answer” value=””>
から
<input type=”hidden” id=”answer” name=”answer” value=””>
へ戻す
投票画面の作成
投票画面の作成
#05 投票画面を作ってみよう
http://dotinstall.com/lessons/poll_php_v2/9705
を参考に、投票画面の作り込み
編集するのは index.php
まず、
http://サーバーIP/poll_php
にアクセスしてエラーがないのを確認
投票は form で行う
アクションを行うのは、同じファイル
つまり index.php なので
action=”” というように空でOK
もし、 action.php などを作成して行うなら
action=”action.php” というようになる
今回なら
<form action=”” method=”POST”>
今回の場合、画像が欲しいので
フリー画像 素材 料理
などで検索して、画像を4つ用意する
そして、4つの写真の名前を
photo1.jpg
photo2.jpg
photo3.jpg
photo4.jpg
という名前にして保存し
サーバーに転送
私の場合、Ubuntu がクライアントマシンなので
cd $HOME/ピクチャ/
で画像がおいてあるフォルダに移動して
scp *.jpg 192.168.10.151:/var/www/html/poll_php/
でファイルを転送
windows なら
winscp あたりで転送できるし
Android なら AndFTP Pro で scp が使えるので
こちらで転送することも可能
ipod touch の場合 scp が使えるのが見当たらないので
SFTP で転送
そして、画像に
class=”candidate”
data-id=”1″
というように番号を振っておく
これは後の jQuery 処理に使う
ソースにすると
<img src=”photo1.jpg” class=”candidate” data-id=”1″>
<img src=”photo2.jpg” class=”candidate” data-id=”2″>
<img src=”photo3.jpg” class=”candidate” data-id=”3″>
<img src=”photo4.jpg” class=”candidate” data-id=”4″>
というように4つ用意する
そして、送信するために
ボタンを作成する
<input type=”submit” value=”投票する”>
そして、
クリックされた写真に応じて番号が入るようにする
投票の仕方は
<input type=”hidden” id=”answer” name=”answer” value=””>
で
クリックされた写真に応じて1~4の値が入るようになる
とりあえず、ここまでやって写真が表示されるか確認
動画みたいに4分割されていないけど
ブラウザを縮小してみると分割されるので問題ないと思う
次に、
<input type=”hidden” id=”answer” name=”answer” value=””>
のところに値が入るようにするので
jQuery を使うことになる
ライブラリをダウンロードして保存でもいいけど
どのみちネットにつながってるなら
リンクしたほうが効率的なので
<script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js”></script>
で読み込む
追記するのは head タグの中
これで、このときの処理を form タグの下あたりに追記していく
PHP投票システムの設定ファイル作成
PHP投票システムの設定ファイル作成
#03 設定ファイルを作ろう
http://dotinstall.com/lessons/poll_php_v2/9703
をもとに設定ファイルを作成
vim config.php にアプリ共通の設定を作成
まずは、定数を define() で作成していく
DB関連とサイトURLは定数にしておくと書くのが楽になる
define(‘DSN’, ‘mysql:host=localhost;dbname=dotinstall_poll_php’);
define(‘DB_USER’, ‘dbuser’);
define(‘DB_PASSWORD’, ‘nk31gsfms’);
define(‘SITE_URL’, ‘http://192.168.10.151 /poll_php/’);
こうすることで、後で変更するのも楽になる
エラー出力方法も指定しておく
これはほぼ決まり文句で
NOTICE以外は全て表示するので
error_reporting(E_ALL & -E_NOTICE);
また、一部セッションを使うので
session の設定を行う
session_set_cookie_params(0,’/poll_php/’);
これで、poll_php ディレクトリの中だけセッションが有効になる
次に、よく使う関数もファイルを作成して
そこに登録しておく
vim function.php でファイルを作成して
そこにまとめる
参考にするのは
#04 よく使う関数を登録しておこう
http://dotinstall.com/lessons/poll_php_v2/9704
ここにまとめるのは
DB接続関連
そして
HTMLへのエスケープ出力関連
まず、DB接続関係
DB接続は try catch 形式で行う
catch の部分には、うまくいかなかったときの処理を書く
catch(PDOException $e){
echo $e->getMessage();
exit;
}
接続できたときの処理は
try のところに記述する
return でPDOオブジェクトを返すようにする
オプションは
DSN
DBUSER
DB_PASSWORD
という設定ファイルで作った定数を指定する
エスケープに関しては、
htmlspecialchars() を使うけど、長いし面倒なので
h() でできるように設定しておく
function h($s){
return htmlspecialchars($s, ENT_QUOTES, “UTF-8”);
}
とすることで、うまくいかなかったときのエラーが
出力される
ここまでできたら、index.php というホーム画面を作成
require_once() で
config.php
functions.php を読み込む
PHPでログアウト処理の実装
ログアウト処理の実装
#19 ログアウト処理を実装しよう
http://dotinstall.com/lessons/sns_php_v2/9619
を参考に
PHPでのログアウト処理の実装
vim logout.php
でファイルを作成
最初のPHPの部分
require_once() によるファイル読み込み
そして、セッションの開始は
そのままコピペでOK
require_once(‘config.php’);
require_once(‘functions.php’);
session_start();
そして、セッションの中身を空の配列にする
$_SESSION =array();
次に、セッションクッキーの削除
これは、空の値と有効期限を過去の時間にすることで
実現できる
86400は一日の秒数
if(isset($_COOKIE[session_name()])){
setcookie(session_name(),”,time()-86400,’/sns_php/’);
}
そして、セッション情報の破棄するので
session_destroy();
ここまでできたら、ログイン画面に戻すので
header(‘Location: ‘.SITE_URL.’login.php’);
とする
これで実行すると
ログイン機能が実装されているのが実感できる
ユーザプロフィールの表示
ユーザプロフィールの表示
#18 ユーザープロフィールを表示する
http://dotinstall.com/lessons/sns_php_v2/9618
を参考に
ユーザーの詳細情報を表示するためのプロフィールページを実装
編集するのは profile.php
一覧表示はいらないので
<ul>
<?php foreach($users as $user) : ?>
<li><a href=”profile.php?id=<?php echo h($user[‘id’]); ?>”><?php echo h($user[‘name’]); ?></a></li>
<?php endforeach; ?>
</ul>
は削除
代わりに、プロフィールを表示するコードを記述
<h1>user profile</h1>
<p>name: <?php echo h($user[‘name’]); ?></p>
<p>email : <?php echo h($user[‘email’]); ?></p>
そして、index.php に戻るためのリンクもつくる
<p><a href=”index.php”>一覧へ</a></p>
あと、SQL実行のため
php ソース部分に
$sql =”select * from users where id = :id limit 1″;
$stmt=$dbh->prepare($sql);
$stmt->execute(array(“:id”=>(int)$_GET[‘id’]));
これで、実行してユーザ名をクリックすると
プロフィール画面になる
このとき
http://192.168.10.151/sns_php/profile.php?id=1
というように、profile.php?=ユーザIDとなっている
この番号を存在しないIDにすると
そのユーザは存在しないというエラーもでる
PHP+MySQL でユーザ情報表示
PHP+MySQL でユーザ情報表示
#16 ユーザー情報を表示しよう
http://dotinstall.com/lessons/sns_php_v2/9616
を参考に
ログインしているユーザ情報の表示をする
編集するファイルは index.php
まずは php部分の編集
セッションに me が入っているので
$me =$_SESSION[‘me’];
として $me に格納
次に、どのユーザでログインしているか表示するので
HTML部分に
Logged in as <?php echo h($me[‘name’]); ?> (<?php echo h($me[‘email’]); ?>)
としてDBから
ユーザ名とメールアドレスを取得して表示
また、ログアウト機能も作っておく
<a href=”logout.php”>log out</a>
ここまでが個人ユーザ情報の取得と表示
ユーザ一覧を取得して表示するには
PHP部分で
$dbh = connectDb();
$users = array();
$sql =”select * from users order by created desc”;
foreach($dbh->query($sql) as $row){
array_push($users,$row);
}
これで、次にHTML部分にリスト表示するための準備
<h1>ユーザ一覧</h1>
の下に
<ul>
<?php foreach($users as $user) : ?>
<li></li>
<?php endforeach; ?>
<ul>
とする
次に
一覧を表示したいので
<li></li>
の間に
<php echo h($user[‘name’]); ?>
とする
さらに各ユーザ情報を作成して
そこにリンクさせるなら
<a href=”profile.php?id=<?php echo h($user[‘id’]); ?>”><php echo h($user[‘name’]); ?></a>
というようにする
これで、ユーザ一覧に名前がでればOK
そして、profile.php に関しては index.php に近いソースなので
cp index.php profile.php
でコピーして編集する
プロフィール情報なので、一覧のところのSQLを変える
$sql =”select * from users where id = :id limit 1″;
として
編な値が入らないのように
(int )というように型を指定しておく
$stmt = $dbh->execute(array(“:id”=>$_GET[‘id’]));
とすれば、現在ログインしているユーザIDが取得できる
$user = $stmt->fetch();
としてSQLの実行結果を $user へ格納
そして
if(!$user){
echo “no such user !”;
exit;
}
とすれば、ユーザが検出できないときには
エラーメッセージがでるようになる
PHPでログイン処理の実装
#15 ログイン処理を完成させよう
http://dotinstall.com/lessons/sns_php_v2/9615
を参考に、ログイン処理の実装
エラーメッセージの表示と動作確認する
変更するのは
login.php
<?php echo h($err[‘email’]); ?>
<?php echo h($err[‘password’]); ?>
を input 要素のところに追記して
それぞれ空白とかのエラー対応メッセージを表示する
また、メールアドレスに関しては
value=””に
<?php echo h($email); ?>
を追記してメールアドレスを表示したままにできるようにする
ここまでできたら、動作確認
ログインできたのを確認したら
if (empty($err)) {
}
の中にセッションハイジャック対策をする
session_regenerate_id(true);
を追記する
$_SESSION[‘me’]=$me;
header(‘Location: ‘.SITE_URL);
exit;
でindex.php に飛ぶようにする
これで、ログイン画面からアクセスして
メールアドレス
パスワードを入力して
ログインして
ユーザ一覧
と表示されていたら成功
これで、次は index.php のページの作り込みになる
メールアドレスの登録チェック
メールアドレスの登録チェック
まずメールアドレスの形式チェック
メールアドレスが空でないか
メールアドレスとパスワードか正しいか
パスワードが空でないか
これらをチェックするようにする
メールアドレスが空の場合
パスワードが空の場合
これらは、signu.phpからコードをコピペ
メールアドレスが空なのか判定するには
signu.phpにあった
ユーザー関数の
emailExists()を使う
ただ、これは、存在しているか調べるので
否定形式て
if(!emailExists($email,$dbh)){
$err[‘email’]=”このメールアドレスは登録されていません”;
}
とすればok
メールアドレスの形式が不正か調べるには
if(!filter_var($email, FILTER_VALIDATE_EMAIL)){
$err[‘email’]=”メールアドレスの形式が正しくありません”;
}
とする
メールアドレスとパスワードがただしくない場合の処理は
まず、そういったユーザーがいるか調べる
$me = getUser($email,$password, $dbh);
で結果を変数へ格納
ちなみにgetUser()は
ユーザー関数
function getUser(){
}
て実装していく
また、エラーのチェックの場所が違うため
$err = array();
の下へ切り取って貼り付ける
そして、ユーザー関数
getUser()は
function getUser($email,$password,$dbh){
$sql=”select * from users where email = :email and :password = $password limit 1″;
$stmt = $dbh->prepare($sql);
$stmt->execute(array(“:email”=>$email,”:password”=>getSha1Password($password)));
$user = $stmt->fetch();
で取得した結果を $userへ格納
あとは、データの有無を
return $user ? $user :false;
として、データがあるなら
ユーザーを返し、ないならfalseを返す
これで、あとはifて判定する
if(!$me){
$err[‘password’]=”パスワードとメールアドレスが正しくありません”;
}
と表示する
$meは、getUser()て取得した内容が格納されている
また、もっと短くコードを書くには
if(!$me = getUser($email,$password,$dbh)){
$err[‘password’]=”メールアドレスとパスワードが正しくありません”;
}
というように
ifの条件式をまとめることもできる