SHINYA TECH

公務員(行政職)から34歳でエンジニア転職した人

#23 Web版読書ログサービスの作成 ~ 読書ログの一覧表示(XSS対策含む) ~

f:id:kshinya-tech:20220307051420p:plain

前回、登録ページと一覧ページのHTMLに共通する箇所を共通化させました。

その際、HTMLをベタ打ちで書いていた箇所をPHPでデータベースからデータを取得し、一覧表示できるようにしました。

テーブルにデータがない状態を再現する方法とXSS(クロスサイトスクリプティング)対策についても学びました。


↓作成したページ f:id:kshinya-tech:20220307053052p:plain

1. データベースからデータを取得

mysqli_query()mysqli_resultオブジェクトを取得し、

mysqli_fetch_assoc()mysqli_resultオブジェクトから、フィールド名(カラム名)を引数とする連想配列として取り出す shinya-tech.com

2. HTMLでデータを表示

foreach文を使用し、ループ処理を行う。

shinya-tech.com

3. データがない場合

if文を用いて条件分岐を行う。

なお、データがない状態を作るためにTRUNCATE TABLE文を使う。

TRUNCATE TABLE文はMySQLで特定のテーブルの全データを削除するときに用いる。

TRUNCATE TABLE <全データを削除したいテーブル名>;
# 例えば、reviewsテーブルを削除したい場合は、
TRUNCATE TABLE reviews;

4. XSS対策

XSSとは

XSS(クロスサイトスクリプティング)とは、ユーザの入力データを表示する箇所のHTML生成の実装に不備があると発生する脆弱性のこと。

JavaScriptのコード(<script>…</script>)を入力された場合、XSS対策をしていないと、スクリプトが実行されてしまう。

例えば、Cookie情報を抜き出すスクリプトが実行されると、Cookie情報からなりすましログインをされてしまう。

結論、ユーザの入力内容を表示する箇所ではXSS対策が必須

XSS対策の方法

htmlspecialchars()を使って、HTML特殊記号をエスケープする。

htmlspecialcars($string, $flags, $encoding)
* $string : 変換する文字列
* $flags : 処理の仕方を指定するフラグ
* $encoding : 文字を変換する時に使用するエンコーディング

ユーザが入力してデータベースに保存された<script>...</script>をエスケープするなら

htmlspecialchars('<script>...</script>', ENT_QUOTES, 'UTF-8')

書いたコード

index.php

<?php

require_once __DIR__ . '/lib/escape.php';
require_once __DIR__ . '/lib/mysqli.php';

function listReviews($link)
{
    $reviews = [];
    $sql = 'SELECT title, author, status, score, summary FROM reviews';
    $results = mysqli_query($link, $sql);

    while ($review = mysqli_fetch_assoc($results)) {
        $reviews[] = $review;
    }

    mysqli_free_result($results);

    return $reviews;
}

$link = dbConnect();
$reviews = listReviews($link);

// layout.php内の変数に渡す
$title = '読書ログの一覧';
$content = __DIR__ . '/views/index.php';

// layout.phpを取り込む
include __DIR__ . '/views/layout.php';

views/index.php

<a href="new.php">読書ログを登録する</a>
<main>
    <?php if (count($reviews) > 0) : ?>
        <?php foreach ($reviews as $review) : ?>
            <section>
                <h2>
                    <?php echo escape($review['title']); ?>
                </h2>
                <div>
                    <?php echo escape($review['author']); ?>&nbsp;/&nbsp;
                    <?php echo escape($review['status']); ?>&nbsp;/&nbsp;
                    <?php echo escape($review['score']); ?></div>
                <p>
                    <?php echo nl2br(escape($review['summary'])); ?>
                </p>
            </section>
        <?php endforeach; ?>
    <?php else : ?>
        <p>読書情報が登録されていません。</p>
    <?php endif; ?>
</main>

lib/escape.php

<?php

function escape($string)
{
    return htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
}

参考URL

nl2brを使った自動での<br />タグの挿入

techacademy.jp

HTML上で半角スペースを空ける方法

&nbsp;←これって何の呪文ですか? - Qiita