PDF文件保护不受外部访问。仅对经过身份验证的用户可用。 WordPress上传目录

时间:2018-07-26 10:12:13

标签: wordpress pdf nginx indexing hotlinking

我正在运行一个网站,我想保护WordPress上载文件夹内的所有PDF文件免受外部访问和热链接。

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

我不希望更改默认的上载目录,因为PDF超过1000个,文件名随机,并附有不同日期的各种帖子。

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

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

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;
        }
    }
}

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

任何帮助或建议将不胜感激。

谢谢。

4 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

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

然后检查用户是否通过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();
        }
    }
}

希望这会有所帮助。

答案 2 :(得分:0)

因此,在尝试所有答案等之后,最终我发现,当site.conf#1与登录用户一起使用URL以https://开头的PDF文件时,却没有处理以前在URL中使用http://的以前的上传。我不得不将wp_posts表更新为 https ://example.com/wp-content/uploads/,它终于保护了(仅)PDF文件免遭直接访问。

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

感谢所有帮助。

答案 3 :(得分:0)

我是通过 .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