2
1

More than 1 year has passed since last update.

[WordPress] WordPress 非ログイン時に wp-content/uploads/ へのアクセスを拒否する

Last updated at Posted at 2021-03-23

WordPress のメディアファイルは静的ファイルなので、WordPress のログイン・非ログインにより表示・非表示を制御するということができません。
ただ会員制サイトとかだと、ログインしてない時に直接アクセスさせたくないとかって要望もあるので、対応できるようにしてみました。

まず、WordPress がインストールされてるディレクトリに以下のファイルを作成します。

uploads-files.php
<?php
require __DIR__.'/wp-load.php';
if ( is_user_logged_in() ) {
    $file = realpath( ABSPATH . sanitize_text_field($_GET['file']) );

    // アップロードディレクトリ以下のファイルのみを対象にする
    $upload_dir = wp_get_upload_dir();
    if ( $file && strpos( $file, $upload_dir['basedir'] ) == 0 ) {
        $mime_type = mime_content_type( $file );

        // アップロードが許可されている mime type のファイルのみを対象にする
        $allowed_mime_types = get_allowed_mime_types();
        if ( in_array( $mime_type, $allowed_mime_types, true ) ) {
            if ( $mime_type === 'image/svg' ) {
                $mime_type = 'image/svg+xml';
            }
            header( 'Expires: 0' );
            header( 'Cache-Control: must-revalidate' );
            header( 'Pragma: public' );
            header( 'Content-Length: ' . filesize( $file ) );
            header( 'Content-Type: ' . $mime_type );
            header( 'X-Content-Type-Options: nosniff' );
            while ( ob_get_level() ) { ob_end_clean(); }
            readfile( $file );
            exit;
        } else {
            wp_die(
                '403 Forbidden',
                get_bloginfo('name').' - Forbidden',
                ['response' => 403]
            );
        }
    } else {
        wp_die(
            '404 Not Found',
            get_bloginfo('name').' - Not Found',
            ['response' => 404]
        );
    }
} else {
    wp_die(
        '401 Unauthorized',
        get_bloginfo('name').' - Unauthorized',
        ['response' => 401]
    );
}

そんで、Nginx の設定ファイルに以下の rewrite ルールを追加。
合わせて /uploads-files.php に対して直接アクセスされないように internal に設定しておきましょうかね。

nginx.conf
rewrite ^(/wp-content/uploads/.*)$ /uploads-files.php?file=$1 last;
location = /uploads-files.php {
    internal;

    expires        off;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_index index.php;
    include       fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
}

これで /wp-content/uploads/ 以下へのリクエストがくると /uploads-files.php で処理されるようになります。
/uploads-files.php の中で WordPress にログインしているか( is_user_logged_in() )をチェックしているので安心ですね。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1