我正在运行一个网站,我想保护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错误。
任何帮助或建议将不胜感激。
谢谢。
答案 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。