PDF 文件保护免受外部访问。只有经过身份验证的用户才能访问。 WordPress上传目录

PDF files protection from external access. Accessible only to authenticated users. WordPress uploads directory

我是 运行 一个网站,我想保护 WordPress 上传文件夹中的所有 PDF 文件免受外部访问和热linking。

我已经在使用用户身份验证来保护附加到这些文件的帖子,但用户身份验证不保护直接 link 到 PDF 文件或搜索引擎对这些文件的索引。

我不想更改默认的上传目录,因为 PDF 超过 1000 个,文件名随机,并且附加到不同日期的各种帖子。

站点托管在 Debian VPS 上,带有 Nginx、php5-fpm 和 MariaDB。

到目前为止,我已经测试了以下内容:

site.conf 1

location /wp-content/uploads/ {
    location ~* \.(pdf)$ {
        valid_referers blocked example.com *.example.com;
        if ($invalid_referer) {
            return 301 https://example.com/services/login-error.html;
        }
    }
}

site.conf 2

location /wp-content/uploads/ {
    location ~* \.(pdf)$ {
        valid_referers blocked example.com *.example.com;
        if ($invalid_referer) {
            deny all;
            return 403;
        }
    }
}

不幸的是,none 以上配置按预期工作。他们阻止外部访问,但他们也将经过身份验证的用户重定向到 403 或 301 错误。

如有任何帮助或建议,我们将不胜感激。

谢谢。

这里最好的方法是使用 http://nginx.org/r/auth_request 来确定,在给定的 location 内,用户是否已通过身份验证并应授予访问权限。不过,您必须为 WordPress 找出正确的 end-point。

另一种选择是将所有文件移动到 http://nginx.org/r/internal location,并使用处理旧 [=] 的新脚本中的 X-Accel-Redirect HTTP 响应 Header 字段10=],所有外部链接都指向该链接,以仅将那些经过身份验证的客户端重定向到内部 location,如上所述。

不要将未登录的用户重定向到错误 URL,而是将文件路径传递到页面 - 可以是您的主页。添加以下规则。

rewrite ^/wp-content/uploads/(.*)\.(?!js|css|png|jpe?g|gif)(.*)$ /?dwnld_file=.

然后检查用户是否通过 WordPress 登录,如果有效则提供访问权限。将以下内容添加到您的主题 'functions.php'.

//init hook
add_action( 'init', 'file_init' );
function file_init() {
    if ($_REQUEST[ 'dwnld_file' ] != '' ) {
        if ( ! is_user_logged_in() ) { // if not logged-in
            auth_redirect(); //redirect to login page
            // wp_redirect( 'https://example.com/services/login-error.html' ); // or some other page
            exit;
        }
        else {
            check_download_file( $_REQUEST[ 'dwnld_file' ] ); // if logged-in pass file to download
        }
    }
}

//function to download file
function check_download_file( $file ) {
    $upload = wp_upload_dir();
    $file = $upload[ 'basedir' ] . '/' . $file;
    if ( !is_file( $file ) ) {
        status_header( 404 );
        die( 'File not found.' );
    }
    else {
        $mime = wp_check_filetype( $file ); 
        if( false === $mime[ 'type' ] && function_exists( 'mime_content_type' ) )
            $mime[ 'type' ] = mime_content_type( $file );

        if( $mime[ 'type' ] )
        {
            $mimetype = $mime[ 'type' ];        

            header( 'Content-type: ' . $mimetype );
            $last_modified = gmdate( 'D, d M Y H:i:s', filemtime( $file ) );
            $etag = '"' . md5( $last_modified ) . '"';
            header( "Last-Modified: $last_modified GMT" );
            header( 'ETag: ' . $etag );
            header( 'Expires: ' . gmdate( 'D, d M Y H:i:s', time() + 100000000 ) . ' GMT' );

            readfile( $file );
            die();
        }
    }
}

希望对您有所帮助。

所以,在尝试了所有的答案和更多之后,我最终发现,当 site.conf #1 正在与登录用户一起处理以 URL 开头的 PDF 文件时对于 https://,它不适用于以前在 URL 中包含 http:// 的上传。我不得不将 wp_posts table 更新为 https://example.com/wp-content/uploads/ 并且它最终(仅)保护了 PDF 文件直接访问。

当然,这是一个粗略的解决方法,请记住,此方法还将保护公开可用的 PDF 文件。

感谢大家的帮助。

我是通过 .htaccess 阅读 wordpress_logged_in cookie 完成的。

保护上传文件夹中的所有文件:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTP_COOKIE} !.*wordpress_logged_in.*$ [NC]
    RewriteCond %{REQUEST_URI} ^(.*?/?)wp-content/uploads/.* [NC]
    RewriteRule . http://%{HTTP_HOST}%1/wp-login.php?redirect_to=%{REQUEST_URI} [L,QSA]
</IfModule>

仅保护部分文件扩展名:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{HTTP_COOKIE} !.*wordpress_logged_in.*$ [NC]
    RewriteCond %{REQUEST_URI} ^(.*?/?)wp-content/uploads/.*\.(?:gif|png|jpe?g|pdf|txt|rtf|html|htm|xlsx?|docx?|mp3|mp4|mov)$ [NC]
    RewriteRule . http://%{HTTP_HOST}%1/wp-login.php?redirect_to=%{REQUEST_URI} [L,QSA]
</IfModule>

阅读更多here