bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. Laravelで安全なファイルアップロードを書くためのベストプラクティス

Laravelで安全なファイルアップロードを書くためのベストプラクティス

Mar 11, 2026 Laravel bucket-sort

Laravelにはファイルアップロードを扱う便利なAPIが用意されています。 ただし、ファイルアップロード機能はセキュリティ事故につながりやすい部分でもあるため、いくつか基本的な設計方針を押さえておく必要があります。

自分用の覚え書きとして、Laravelで安全にファイルアップロードを実装する際のベストプラクティスを整理しておきます。

1 バリデーションで入口を制限する

まずはアップロードされるファイルをバリデーションで制限します。

例えば画像アップロードの場合は次のように書きます。

$request->validate([
    'avatar' => [
        'required',
        'file',
        'image',
        'mimes:jpg,jpeg,png,webp',
        'max:5120', // KB(5MB)
        'dimensions:min_width=64,min_height=64,max_width=6000,max_height=6000',
    ],
]);

ポイントとしては次のようなものです。

  • file でファイルであることを確認
  • image で画像として読み取れることを確認
  • mimes で許可する拡張子を限定
  • max でサイズ制限

サイズ制限は 巨大ファイルによるDoS攻撃対策にもなります。

2 保存先はWeb公開ディレクトリ外にする

アップロードされたファイルは、できれば Web公開ディレクトリの外に保存します。

Laravelのデフォルトの保存先は次のディレクトリです。

storage/app

例えば次のように保存します。

$path = $request->file('avatar')->store('uploads/avatars');

実際の保存場所は次のようになります。

storage/app/uploads/avatars/xxxxx.jpg

この場所はWebから直接アクセスできないため、安全性が高くなります。

3 ファイル名はサーバー側で生成する

ユーザーが指定したファイル名は基本的に信用しません。

Laravelの store() メソッドを使うと、ランダムなファイル名で保存されます。

$path = $request->file('avatar')->store('uploads/avatars');

元のファイル名は表示用としてDBに保存しておく程度にします。

$file = $request->file('avatar');

$originalName = $file->getClientOriginalName();
$path = $file->store('uploads/avatars');

4 拡張子とMIMEタイプの両方をチェックする

HTTPリクエストの Content-Type はクライアント側で簡単に偽装できます。

そのため次のようなチェックを組み合わせます。

  • image
  • mimes
  • 必要に応じて mimetypes

例:

$request->validate([
    'avatar' => [
        'required',
        'file',
        'image',
        'mimes:jpg,jpeg,png,webp',
        'mimetypes:image/jpeg,image/png,image/webp',
        'max:5120',
    ],
]);

5 ダウンロードはアプリケーション経由で配信する

アップロードしたファイルをユーザーにダウンロードさせる場合は、 アプリケーション経由で配信する方法が安全です。

use Illuminate\Support\Facades\Storage;

public function download(string $id)
{
    $file = UploadedFileModel::findOrFail($id);

    return Storage::download($file->path, $file->original_name);
}

この方法なら、ダウンロード前に 認可チェックを挟むこともできます。

6 画像は再エンコードするとさらに安全

画像アップロードの場合は、アップロードされたファイルをそのまま保存するのではなく 一度読み込んで再エンコードして保存する方法もあります。

考え方としては

  • アップロードされたバイナリをそのまま保存しない
  • 画像として読み込んで再保存する

という方法です。

実務では次のようなライブラリを使うことが多いです。

  • Intervention Image
  • ImageMagick

実務でよく言われる安全設計

実務では、次のような設計がよく推奨されます。

① 保存ファイル名はサーバー生成

3f8a2c9b.jpg

などランダム名を使います。

② Web公開ディレクトリ外に保存

例えば

/var/data/uploads

などWebから直接アクセスできない場所に保存します。

③ 拡張子ホワイトリスト

許可する拡張子のみ受け付けます。

jpg
png
pdf

④ ファイルサイズ制限

例えば

10MB

などの制限を設けます。

⑤ 必要に応じてウイルススキャン

環境によっては

  • ClamAV

などのウイルススキャンを組み込む場合もあります。

まとめ

Laravelで安全にファイルアップロードを実装するための基本ポイントは次の通りです。

  • バリデーションでファイル種類とサイズを制限
  • 保存先はWeb公開ディレクトリ外
  • ファイル名はサーバー生成
  • MIMEタイプだけに依存しない
  • ダウンロードはアプリケーション経由
  • 可能なら画像は再エンコード

Laravelの store() や Storage を使うと、比較的シンプルなコードで安全なファイルアップロード処理を書くことができます。

ファイルアップロードはセキュリティ事故につながりやすい部分でもあるので、 基本的な対策は忘れないようにしておきたいところです。

Laravel ファイルアップロード セキュリティ PHP バリデーション Storage
← ファイルアップロード機能で注意すべき代表的な脆弱性 Laravel FormRequestのauthorize()をちゃんと書くべき理由 →

Related Posts

  • Laravelのレート制限(throttle:5,1)とは何か Mar 27, 2026
  • Laravel FormRequestのauthorize()をちゃんと書くべき理由 Mar 12, 2026
  • Laravel の Event / Listener で Pub/Sub を実装する Apr 2, 2026
  • PHP/Laravel で値の状態を判定するヘルパ関数まとめ Mar 30, 2026

Table of Contents

  • 1 バリデーションで入口を制限する
  • 2 保存先はWeb公開ディレクトリ外にする
  • 3 ファイル名はサーバー側で生成する
  • 4 拡張子とMIMEタイプの両方をチェックする
  • 5 ダウンロードはアプリケーション経由で配信する
  • 6 画像は再エンコードするとさらに安全
  • 実務でよく言われる安全設計
  • まとめ

Recent Posts

  • Laravel の Event / Listener で Pub/Sub を実装する Apr 2, 2026
  • [C#] delegate と event の仕組みを整理する Apr 1, 2026
  • Pub/Sub パターンとは何か Mar 31, 2026
  • PHP/Laravel で値の状態を判定するヘルパ関数まとめ Mar 30, 2026
  • Filament の dehydrated メソッドとは何か Mar 29, 2026

Categories

  • AWS27
  • C#22
  • .NET20
  • Laravel16
  • Linux12
  • Apache8
  • MySQL8
  • PHP8
  • DynamoDB6
  • Nginx5
  • WordPress4
  • インフラ4
  • Hugo3
  • セキュリティ3
  • .NET Framework1
  • Aurora1
  • Filament1
  • Git1
  • SQS1

Tags

  • AWS
  • C#
  • .NET
  • Laravel
  • PHP
  • MySQL
  • セキュリティ
  • Linux
  • Apache
  • Code Snippet
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • DoS
  • Nginx
  • Windows
  • WordPress
  • パフォーマンス
  • 監視
  • Amazon Linux 2023
  • CMS
  • Docker
  • Ipset
  • Iptables
  • OPCache
  • Webサーバー
  • 認可
  • Aurora
  • Blade
Powered by Hugo & Explore Theme.