WordPressにアップロードしたファイルを特定の人だけダウンロードできるようにする方法
久々のエントリーですが、今回はWordPressで作成したサイト上に特定の人だけがダウンロードできるファイルを掲載したい場合に使えるTipsをご紹介させていただきます。
想定される利用シーン
コロナ禍以降、メンバー制のWebサイト制作やCRMなどの業務用アプリケーションと連携して様々な業務を効率化するための機能開発のご依頼をいただく機会が増えております。
そのようなケースの機能要件として、
- 会員マイページから会員限定のPDF資料をダウンロードできるようにしたい
- 資料請求フォームを送信した人だけパワポの資料をダウンロードできるようにしたい
- 有料会員のみ利用できるダウンロードコンテンツを作りたい
などのご要望をいただくことがありますが、上記の対応には少しカスタマイズが必要です。
実装上のネック
なぜかと言いますと、WordPressの標準機能ではメディアライブラリにアップロードされたファイルは、
%WordPressのインストール先%/wp-content/uploads/yyyy/mm/ ※yyyy=年、mm=月
のディレクトリに自動的に分類されます。
このディレクトリは、Webサイト上で使用する画像やその他ファイルにも利用しているため、アクセス制限をかけることができません。
このため、例えログインが必要なマイページ上にしかこのファイルリンクを設置しなかったとしても、ファイルのURLを共有されてしまうとターゲットのユーザー以外にも簡単にファイルの共有ができてしまいます。
これでは「会員限定」や「資料請求フォーム」の設定をしても、あまり意味を為さないことになってしまいますね。
実装アイデア
ではこのような場合にどうすれば良いか、弊社でも考えてみました。
ポイントは以下の通りです。
- 特定のファイルだけアップロード先のディレクトリを変更する
- 限定ユーザー向けのアップロードディレクトリは直接参照できないようにする
- wp_nonceを使用してダウンロードURLの共有を不可にする
- ファイルのダウンロード処理用のページを作成する
それでは1つずつ実装方法を見ていきましょう。
特定のファイルだけアップロード先のディレクトリを変更する
ACF(Advanced Custom Fields)プラグインを使用している場合、特定のフィールドからアップロードしたファイルの格納先を個別に指定することが可能です。
具体的には、下記のフィルターフックを使用します。
function my_acf_upload_prefilter( $errors, $file, $field ){
/* アップロード先の指定など */
}
add_filter('acf/upload_prefilter', 'my_acf_upload_prefilter', 10, 3);
この際、フィルターに、
acf/upload_prefilter/name={$name}
acf/upload_prefilter/key={$key}
と設定することで、特定のカスタムフィールドのみにこの変更を適用することができますので、限定コンテンツをアップロードするフィールドを指定することで他のファイルとアップロード先を分けることができるようになります。
限定ユーザー向けのアップロードディレクトリは直接参照できないようにする
アップロード先のディレクトリはファイルURLで直接参照できないように、アクセス制限をかけておきます。
.htaccessを使用する場合には、
Deny from all
としておけば問題ありません。
wp_nonceを使用してダウンロードURLの共有を不可にする
最終的には、
https://intactis.co.jp/download/?file_id=XXXXXX&nonce=XXXXXXXX
のようなURLでファイルをダウンロードできるようにしたいので、リンクには
file_id=添付ファイルのアタッチメントID
nonce=有効期限付きの暗号キー(wp_nonce)
を含めるようにしておきます。
ファイルのダウンロード処理用のページを作成する
これはあくまでシステム処理用のページですので、中身のコンテンツは作成する必要ありません。
空の固定ページなどを使用し、「download」などのスラッグを設定しておきます。
そして、このページでは、
- GETパラメータ(file_id)から対象ファイルを取得する
- GETパラメータ(nonce)からwp_nonceの有効期限をチェックする
- どちらも有効であれば対象ファイルのダウンロードを実行する
という処理を作成しておけば実装完了です。
実装例
上記の内容をデモとしてこのサイトでも実装してみました。
まず下記のリンクをクリックしてみてください。
ファイルのURLをクリックしても直接ファイルを参照できないことがおわかりいただけたかと思います。
次に下記のリンクをクリックしてみてください。
この場合には、dl_test.pdfというファイルがダウンロードできたと思います。
仮にこのダウンロードURLを共有されたとしても、nonce=XXXXXXXXのパラメータには有効期限があるため、有効期限切れのリンクではファイルのダウンロードができません。
更にこのwp_nonceの有効期限(標準では24時間)を必要に応じて変更しておけば、より実用性が高くなるのではないかと思います。
まとめ
文字だけではわかりにくいので上記の実装をイラストでまとめてみました。
いかがだったでしょうか?
上記は弊社で考えた実装アイデアの一例ですのでまったく違った対応方法もありそうですが、WordPressはカスタマイズの幅が広く、自由な発想でカスタマイズができますので、他にも「こんな機能を実装したいんだけど」というご要望がありましたら、ぜひお気軽にお問い合わせください。