コトの発端
ログインしている人だけが見られるページとかはよくあるけど、画像とかをドキュメントルートに置いているとログインしてなくても見られちゃうよね。
概要
ログイン認証が必要なPHPファイルを作成して、メディアタイプを指定してからファイルを出力してあげればOK。
サーバ内の実ファイルのパスはパラメータに格納すると、攻撃(ディレクトリトラバーサル)の的になるからだめだよ。
実装サンプル
セッションにて保持しているユーザ情報とGETパラメータに応じて、データベースに問い合わせ、メディアを返すプログラム。
KINDが1だと動画、2だとCSVを返すようにしている。
<?php
//DBアクセス情報
require("../../dbinfo.php");
//ログイン認証処理→ログインしてなければ所定のページへ飛ぶ実装を想定。
require_logined_session();
$LOGINED_ID = $_SESSION['LOGINED_USERID'];
//GETパラメータの取得
//レコードIDと、メディア種別→1.動画 2,CSV
$RECORDID = filter_input(INPUT_GET, "RECORDID");
$KIND = filter_input(INPUT_GET, "KIND");
//DBへの問い合わせ。所有権の確認もここで行っている。
//DBにローカルのファイルパスが格納されている。
//間違ってもURLにファイルのパスを格納しちゃだめだぞ。ディレクトリトラバーサル食らうぞ。
$res = false;
try{
$dbh = new PDO($dsn, $user,$password,array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_EMULATE_PREPARES => false));
$chkSQL = "
select
RECORDID,
MOVIE_FILEPATH,
CSV_FILEPATH
from
T_RECORD
where
RECORDID = :RECORDID
and
OWNER_USERID = :OWNER_USERID
;
";
$chkStmt = $dbh->prepare($chkSQL);
$chkStmt->bindParam(":RECORDID", $RECORDID);
$chkStmt->bindParam(":OWNER_USERID", $LOGINED_ID);
$chkStmt->execute();
if($chkResult = $chkStmt->fetch()){
$res = true;
$path_movie = $chkResult["MOVIE_FILEPATH"];
$path_csv = $chkResult["CSV_FILEPATH"];
}
else{
$res = false;
}
}
catch(PDOExeption $e){
$res = false;
}
$dbh = null;
//DBからのパス取得に失敗してれば403返そうか。
if($res === false)
{
http_response_code(403);
exit;
}
//GETのKINDによってメディアの分岐
if($KIND=="1"){
//1.動画の場合
$path=$path_movie;
if (file_exists($path)) {
header("Accept-Ranges: bytes");
header('Content-Type: video/mp4');
header('Content-Length: '. filesize($path));
header('Content-Disposition: inline; filename="'. rawurlencode(basename($path)) .'"');
ob_end_clean();
readfile($path);
}
else{
http_response_code(404);
}
}
else if($KIND=="2"){
//2.CSVの場合
$path=$path_csv;
if (file_exists($path)) {
header('Content-Type: text/csv');
header('Content-Length: '. filesize($path));
header('Content-Disposition: inline; filename="'. rawurlencode(basename($path)) .'"');
ob_end_clean();
readfile($path);
}else{
http_response_code(404);
}
}
else{
http_response_code(403);
}
exit;
使い方例
Content-Typeを指定して出力しているので、csvや.mp4などに直接アクセスするような感覚で使用できる。
例えば、パラメータ付きURLをメディアとして、HTMLタグに組み込んだり、javascriptの動画として指定できたりする。
<video src="idmedia.php?RECORDID=12&KIND=1"></video>
いつもの
記事の正確性は無保証です。