一、文件上传
为了让客户端的用户能够上传文件,我们必须在用户界面中提供一个表单用于提交上传文件的请求。由于上传的文件是一种特殊数据,不同于其它的post数据,所以我们必须给表单设置一个特殊的编码:
以上的enctype属性,你可能不太熟悉,因为这常常会被忽略掉。但是,如果http post请求中既有常规数据,又包含文件类数据的话,这个属性就应该显示加上,这样可以提高针对各种浏览器的兼容性。
接下来,我们得向表单中添加一个用于上传文件的字段:
上述文件字段在各种浏览器中可能表现会有所不同。对于大多数的浏览器,上述字段都会被渲染成一个文本框加上一个浏览按钮。这样,用户既可以自行输入文件的路径到文本框中,也可以通过浏览按钮从本地硬盘上选择所要上传的文件。但是,在苹果的Safari中,貌似只能使用浏览这种方式。当然,你也可以自定义这个上传框的样式,使它看起来比默认的样式优雅些。
下面,为了更好的阐述怎么样处理文件上传,举一个完整的例子。比如,以下一个表单允许用户向我的本地服务器上上传附件:
提示:可以通过php.ini中的upload_max_filesize来设置允许上传文件的最大值。另外,还有一个post_max_size也可以用来设置允许上传的最大表单数据,具体意思就是表单中各种数据之和,所以你也可以通过设置这个字段来控制上传文件的最大值。但是,注意后者的值必须大于前者,因为前者属于后者的一部分表单数据。
図 1. Firefox に表示されたアップロード フォーム
このフォームが送信されると、http リクエストが Upload.php に送信されます。 Upload.php で利用可能な情報を正確に示すために、upload.php に情報を出力します。
header('Content-Type: text/plain');
print_r($_FILES);
を使用する場合は、以下の実験を行ってみましょう。上記のフォームを使用して、このブログのロゴをローカル サーバー www.360weboy.me/upload.php にアップロードし、upload.php にどのような情報が出力されるかを確認します:
[名前] => 男の子 .jpg
[種類] => image/jpeg [tmp_name] => D:xampptmpphp1168.tmp
[エラー] =&g t; > )
)
上記はファイルがアップロードされた後、現在アップロードされているファイルに関するすべての情報がグローバル配列に格納されます。しかし、この情報が安全であることを保証できますか? 名前やその他の情報が改ざんされていた場合はどうなるでしょうか?クライアントからの情報には常に注意を払う必要があります。
特定の http リクエストの一部
ファイルのアップロードをよりよく理解するには、クライアントによって送信された http リクエストにどのような特定の情報が含まれているかを確認する必要があります。先ほどアップロードした添付ファイルはこのブログのロゴですので、上記の実験には適していません。そこで、test.text テキスト ファイルを再アップロードしました。このファイルには、具体的には次の内容が含まれています:
コードをコピー
コードは次のとおりです。以下:
コードをコピーします
コードは次のとおりです。
[名前] => test.tx t
[種類] => text/plain
🎜>)
関連するブラウザから送信されたHTTP POSTリクエストを見てみましょう(オプションのヘッダーは省略しています):
コードをコピーします
コードは次のとおりです:
POST /upload.php HTTP/1.1
ホスト: www.360weboy.me
リファラー: http://www.360weboy.me/
multipart/form-data ; 境界=--------------------------24464570528145
コンテンツの長さ: 234
----- ------------------------24464570528145
コンテンツの配置: フォームデータ名 = ファイル名 = test.txt; "
Content-Type: text/plain
360weboy
360days
Web ボーイの生活
----------- -- ----------------24464570528145--
上記のリクエスト形式には注意が必要なフィールドがいくつかあります。 filename と Content-Type はそれぞれ、アップロード ファイル ボックスの形式 (添付ファイル)、ユーザーがローカル ハードディスクからアップロードしたファイルの名前 (test.txt)、およびアップロードされたファイル形式 (text/) を表します。プレーン (テキスト ファイルを表す)。次に、その下に空行が表示されます。これは、アップロードされたファイルの特定のコンテンツです。
2. セキュリティの強化
ファイルアップロードのセキュリティを強化するには、$_FILES グローバル配列の tmp_name と size をチェックする必要があります。 tmp_name が指すファイルが、/etc/passwd のようなものを指すのではなく、実際にユーザーがクライアントにアップロードしたファイルであることを確認するには、PHP の関数 is_uploaded_file() を使用して判断できます。 🎜>
$filename = $_FILES[' attachment']['tmp_name'];
if (is_uploaded_file($filename)) {
/* アップロードされたファイルです */
}
In場合によっては、ユーザーがファイルをアップロードした後、正常にアップロードされたファイルの内容がユーザーに表示されることがあるため、上記のコードを確認することが特に重要です。
もう 1 つ確認する必要があるのは、アップロードされたファイルの MIME タイプです。これは、上で説明した、upload.php の出力配列の type フィールドです。 最初の例でアップロードしたのは画像なので、$_FILES['attachment']['type'] の値は 'image/jpeg' になります。 サーバー側で image/png、image/jpeg、image/gif、image/x-png、image/p-jpeg などの MIME タイプの画像のみを受け入れる予定の場合は、次のようなコードを使用して確認できます。 (例を示します。エラー報告などの特定のコードは、システムのメカニズムに従う必要があります):
コードをコピー コードは次のとおりです。
ご覧のとおり、ファイルの MIME タイプがサーバー側の要件を満たしていることを確認しました。ただし、この MIME タイプの悪意のあるユーザーは偽装される可能性があるため、悪意のあるユーザーが他の有害なファイルをアップロードするのを防ぐだけでは十分ではありません。 たとえば、ユーザーは jpg 画像を作成し、その画像のメタデータに悪意のある php コードを書き込み、接尾辞 php が付いたファイルとして保存しました。この悪意のあるファイルがアップロードされると、サーバー側の MIME タイプ チェックに合格し、画像とみなされ、内部の危険な PHP コードが実行されます。特定の画像メタデータは次のようなものです:
ファイル名 : image.jpg
ファイルサイズ : 182007 バイト
ファイル日付 : 2012:11:27 7:45:10
解像度 : 1197 x 478
コメント : passthru( $_POST['cmd ']); __halt_compiler();
画像メタデータの Comment フィールドに php コードが追加されていることがわかります。したがって、同様の危険な状況が起こらないようにするために、アップロードされたファイルの拡張子に対して必要なチェックを実行する必要があることは明らかです。次のコードは、Mime タイプをチェックするために以前のコードを拡張しています:
$allow_mimes = array(
'image/png' => image/gif' => '.gif',
'image/jpeg' => '.jpg' ,
'image/pjpeg' => '.jpg'
);
$image = $_FILES['attachment'];
if(!array_key_exists($ image['type'], $allow_mimes )) {
die('アップロードしたファイル形式が正しくありません。画像ファイルのみ受け付けます。');
, 0, strrpos($image[ 'name'], '.'));
// アップロードされたファイルの処理を続行します
上記のコードを通じて、メタデータがアップロードされた画像のファイルに php コードが含まれている場合、画像ファイルの名前は「画像形式」というサフィックスを付けて変更されるため、その中の php コードは実行されません。上記のコードは、通常のアップロードされた画像に悪影響を与えることはありません。
セキュリティを向上させるために上記の手順を実行した後、アップロードされたファイルを指定したディレクトリに保存したい場合は、PHP のデフォルト関数 move_uploaded_file を使用してこれを実現できます:
コードをコピー
コードは次のとおりです:
$temp_filename が一時ディレクトリに保存されました ファイルをアップロードし、正常に保存しました対応するディレクトリ内の添付ファイルへ。 */アップロードされたファイルのサイズを取得するために、これはここでは詳細ではありません。あなた自身。
さて、ここではファイルのアップロードについて書くのはやめておきます。この紹介記事がお役に立てば幸いです。