ネット上のファイルをダウンロードするページを作ります。アクセス時のブラウザの表示を次に示します。

ファイルのダウンロード""

ダウンロード時のセキュリティのために、ディレクトリトラバーサル対策とCSRF対策を行います。ディレクトリトラバーサル対策は、リクエストのパスに不正な内容を指定することで、本来アクセス権のないファイルを閲覧、改ざん、削除されてしまう脆弱性のことで、ファイルを開く場合は、固定ディレクトリ+ファイル名にします。CSRF(クロスサイト・リクエストフォージェリ)対策は、ログイン後のユーザーが行える処理の不正実行することで、ユーザーからのリクエストを本人のリクエストだと判別する仕組み「セッションID」を使用します。

ブラウザに「ロード」ボタンを表示する「load.php」を次に示します。ファイル変数「loadfile」に「/file/demo.pdf」、セッションID変数「session_id」にsession_id関数の戻り値をそれぞれ設定し、ダウンロード処理「loadstart.php」を呼び出します。

load.php

<?php
session_start();
?>
<form action="loadstart.php" method='post'>
    <input name="loadfile" type="hidden" value="<?php echo htmlspecialchars('/file/demo.pdf', ENT_COMPAT, 'UTF-8'); ?>" />
    <input name="session_id"  type="hidden" value="<?php echo htmlspecialchars(session_id(), ENT_COMPAT, 'UTF-8'); ?>" />
    <input type="submit" value='ロード' />
</form>

ディレクトリトラバーサル対策とCSRF対策を行い、指定されたファイルをネット上からダウンロードする「loadstart.php」を次に示す。ディレクトリトラバーサル対策のために、受け取ったファイル変数「loadfile」に「..」が含まれていないかチェックし、固定ディレクトリ「/xxxx/xxxx/」の配下でアクセスします。CSRF対策のためにsession_id関数を実行し、受け取ったセッションID変数「session_id」と戻り値を比較し同じであることを確認します。

loadstart.php

<?php

/* ディレクトリトラバーサル対策 */
$DIR_PATH = '/xxxx/xxxx/';
ini_set('open_basedir', $DIR_PATH);

function get_name($str) {
    if (strpos($str, '..') !== false) {
        echo '相対パスは使用不可';
        exit();
    }
    return str_replace('\0', '', $str);
}

$file = get_name(basename($_POST['loadfile']));  //ファイル名取得
$dir = get_name(dirname($_POST['loadfile']));    //ディレクトリ名取得
/* ディレクトリトラバーサル対策 */

/* CSRF対策 */
session_start();
$id = session_id();
$post = $_POST['session_id'];
if (session_id() !== $_POST['session_id']) {
    echo '不正な処理です';
    exit();
}
/* CSRF対策 */

chdir($DIR_PATH . $dir);      //当該ディレクトリに移動
$mime_name = mime_content_type($file);  //ダウンロードするファイルのMIMEタイプを取得
$file_length = filesize($file);
header("Content-Disposition: attachment; filename=$file");
header("Content-Length:$file_length");
header("Content-Type:$mime_name");
readfile($file);
?>

ファイル構成は、同じフォルダにディレクトリ「file」を作成し、作成したディレクトリにpdfファイル「demo.pdf」を置きます。ブラウザから次のURLを入力します。

http://localhost/download/load.php

表示された「ロード」ボタンをクリックすると、pdfファイル「demo.pdf」がダウンロードされます。