簡易掲示板をつくる中でうまく動作せず先日質問し、その後も構成を変えるなどしてとりあえず自分が思ったように動くものにはなりました。
(過去の質問はこちら)
そこで完成したものをご確認頂き、下記の点についてアドバイスを頂ければと思います。
- 記述方法に誤りはないか
- セキュリティ対策は十分か
---バージョン---
MariaDB 10.1.21
PHP 7.0.15
---ファイル構成・機能---
index.php(投稿一覧表示、新規投稿フォーム)
confirm.php(投稿内容確認画面)
complete.php(書き込み完了画面)
db_info.php(データベース接続情報)
encode.php(エスケープ処理)
error.php(エラー表示)
---テーブル定義---
テーブル名:bbsdata
カラム構成:
name | title | day | msg |
---|---|---|---|
varchar(255) | varchar(255) | datetime | text |
投稿者名 | 投稿タイトル | 投稿日時 | 投稿内容 |
---実装したセキュリティ対策---
XSS対策(エスケープ処理)
CSRF対策(トークンの使用)
SQLインジェクション対策(PDOの使用)
(セキュリティ対策についてはしっかりと知識をつけたいと思っています)
以下、ファイルです。
db_info.php
PHP
1<?php 2$dsn = 'mysql:host=localhost; dbname=bbs;charset=utf8'; 3$user = 'bbsuser'; 4$pass = 'bbspass';
encode.php
PHP
1<?php 2function h($str){ 3 return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); 4}
error.php
PHP
1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <title>エラー表示</title> 6</head> 7<body> 8 <p> 9 <?php echo $error; ?> 10 </p> 11</body> 12</html>
index.php
PHP
1<?php 2session_start(); 3$_SESSION['token'] = bin2hex(random_bytes(32)); 4require_once('db_info.php'); 5require_once('encode.php'); 6 7try { 8 $pdo = new PDO($dsn, $user, $pass); 9 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 10 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 11} catch (PDOExeption $e){ 12 $error = 'データベース接続に失敗しました: ' . $e->getMessage(); 13 include 'error.php'; 14 exit(); 15} 16try { 17 $sql = "select * from bbsdata order by day desc"; 18 $result = $pdo->query($sql); 19} catch (PDOExeption $e) { 20 $error = 'データの取得に失敗しました:' . $e->getMessage(); 21 include 'error.php'; 22 exit(); 23} 24?> 25<!DOCTYPE html> 26<html lang="ja"> 27<head> 28 <meta charset="UTF-8"> 29 <title>簡易掲示板</title> 30 <style type="text/css"> 31 body { 32 background-color: #E1EDFF; 33 line-height: 1.5rem; 34 } 35 </style> 36</head> 37<body> 38<h1>簡易掲示板</h1> 39<!-- 投稿フォーム 40こちらからconfirm.phpにポストしたものをconfirm.php内ではセッションに格納しており、未入力欄があった場合にindex.phpに戻っても入力していた項目は保持されるよう、valueにセッションを入れました 41--> 42<form action="confirm.php" method="post"> 43 名前:<input type="text" name="name" value="<?php if(isset($_SESSION['name'])){ echo h($_SESSION['name']); } ?>"><br> 44 タイトル:<input type="text" name="title" value="<?php if(isset($_SESSION['title'])){ echo h($_SESSION['title']); } ?>"><br> 45 メッセージ:<br> 46 <textarea name="msg" rows="10" cols="30"><?php if(isset($_SESSION['msg'])){ echo h($_SESSION['msg']); } ?></textarea><br> 47 <input type="hidden" name="token" value="<?php echo h($_SESSION['token'])?>"> 48 <input type="submit" value="確認画面へ" name="trans"> 49</form> 50<!-- 投稿フォーム終了 --> 51<hr> 52<?php 53$i = 1; 54//投稿一覧表示 55foreach($result as $row) { 56 $s = "<p>($i)タイトル: <strong>%s</strong><br>投稿者: %s 投稿日: %s<br>内容:<br>%s</p>"; 57 printf ($s,h($row['title']), h($row['name']), h($row['day']), nl2br(h($row['msg']))); 58 $i++; 59} 60//投稿一覧終了 61?> 62</body> 63</html>
confirm.php
PHP
1<?php 2session_start(); 3require_once('encode.php'); 4 5//index.phpでのトークンがセットされていなかったら不正アクセスとみなす 6if (!isset($_SESSION['token']) || $_SESSION['token'] === '') { 7 echo '不正なアクセスです。'; 8} 9//トークンなど諸々が正しくセットされていたら 10elseif (isset($_POST['trans'], $_SESSION['token'], $_POST['token']) && $_SESSION['token'] === $_POST['token']) { 11//フォームでポストされたデータをセッションに格納し 12$_SESSION['name'] = $_POST['name']; 13$_SESSION['title'] = $_POST['title']; 14$_SESSION['msg'] = $_POST['msg']; 15?> 16<!DOCTYPE html> 17<html lang="ja"> 18<head> 19 <meta charset="UTF-8"> 20 <title>確認画面</title> 21 <style type="text/css"> 22 body { 23 background-color: #E1EDFF; 24 line-height: 1.5rem; 25 } 26 </style> 27</head> 28<body> 29 <h1>確認画面</h1> 30<?php 31//フォームに未入力項目があればその旨とindex.phpに戻るボタンを表示 32 if ($_SESSION['name'] == "" || $_SESSION['title'] == "" || $_SESSION['msg'] == ""){ 33 if ($_SESSION['name'] == "") { 34 echo "名前を入力して下さい<br>"; 35 } 36 if ($_SESSION['title'] == "") { 37 echo "タイトルを入力して下さい<br>"; 38 } 39 if ($_SESSION['msg'] == "") { 40 echo "メッセージを入力して下さい<br>"; 41 } 42 ?> 43 <a href="index.php">入力画面に戻る</a> 44 </body> 45 </html> 46 <?php 47 } else { 48 //フォームに未入力項目がなければ内容を確認表示しsubmitボタンを押すと再度confirm.php自身にセッションでデータを渡す 49 ?> 50 タイトル: <?php echo h($_SESSION['title']); ?> 51 投稿者: <?php echo h($_SESSION['name']); ?><br> 52 内容:<?php echo nl2br(h($_SESSION['msg'])); ?> 53 <form action="confirm.php" method="post"> 54 <input type="hidden" name="token" value="<?php echo h($_SESSION['token']); ?>"> 55 <input type="submit" value="送信する" name="regist"> 56 </form> 57 </body> 58 </html> 59 <?php 60 } 61} 62//confirm.php自身からポストやセッションが正しく渡されていたらDBにデータをinsertしcomplete.phpへ遷移 63elseif (isset($_POST['regist'], $_SESSION['token'], $_POST['token']) && $_SESSION['token'] === $_POST['token']) { 64 require_once('db_info.php'); 65 66 try { 67 $pdo = new PDO($dsn, $user, $pass); 68 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 69 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 70 } catch (PDOExeption $e){ 71 $error = 'データベース接続に失敗しました: ' . $e->getMessage(); 72 include 'error.php'; 73 exit(); 74 } 75 try { 76 $sql = "insert into bbsdata (name, day, title, msg) values (:name, now(), :title, :msg)"; 77 $s = $pdo->prepare($sql); 78 $s->bindValue(':name', $_SESSION['name']); 79 $s->bindValue(':title', $_SESSION['title']); 80 $s->bindValue(':msg', $_SESSION['msg']); 81 $s->execute(); 82 } catch(PDOExeption $e) { 83 $error = 'データの書き込みに失敗しました: ' . $e->getMessage(); 84 include 'error.php'; 85 exit(); 86 } 87 88 $_SESSION = array(); 89 if (isset($_COOKIE[session_name()])){ 90 setcookie(session_name(), '', time() -3600, '/'); 91 } 92 session_destroy(); 93 header("Location: http://localhost/complete.php/", true, 303); 94 exit(); 95} else { 96//confirm.php自身からポストやセッションが正しく渡されていなかったら不正アクセスとみなす 97 echo '不正なアクセスです。'; 98}
complete.php
PHP
1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <title>完了画面</title> 6 <style type="text/css"> 7 body { 8 background-color: #E1EDFF; 9 line-height: 1.5rem; 10 } 11 </style> 12</head> 13<body> 14 <h1>書き込みが完了しました</h1> 15 <a href="http://localhost/index.php">トップページへ戻る</a> 16</body> 17</html>
以上、
- 記述方法に誤りはないか
- セキュリティ対策は十分か
といった点についてアドバイスの程よろしくお願い致します。
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/04/29 13:52
退会済みユーザー
2017/04/29 14:32
2017/04/29 15:02
2017/04/30 09:13
退会済みユーザー
2017/04/30 13:17
2017/05/01 04:45