如何保护主站点的子域上的文件免于下载而无需在wordpress中使用auth

问题描述 投票:1回答:2

例如我的主域www.example.com这是一个文件共享网站,我们将文件保存在子域中,如server1.example.comserver2.example.com与访客共享。我的问题是如何保护子域(子域可能指向不同的服务器或主机)上的文件直接下载而无需在wordpress / mainsite中进行身份验证。

我目前的代码归功于http://wordpress.stackexchange.com/a/37743/12438

.htaccess文件

RewriteCond %{REQUEST_FILENAME} -s
RewriteRule ^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]

所以我的整个.htaccess代码看起来像

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# BEGIN THIS DL-FILE.PHP ADDITION
RewriteCond %{REQUEST_URI} ^.*wp-content/uploads/.*
RewriteRule ^wp-content/uploads/(.*)$ dl-file.php?file=$1 [QSA,L]
# END THIS DL-FILE.PHP ADDITION

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

# END WordPress

Options -Indexes

但它只能保护wp-content/uploads/*里面的文件是dl-file.php

<?php
ob_start();
require_once('wp-load.php');
require_once ABSPATH . WPINC . '/formatting.php';
require_once ABSPATH . WPINC . '/capabilities.php';
require_once ABSPATH . WPINC . '/user.php';
require_once ABSPATH . WPINC . '/meta.php';
require_once ABSPATH . WPINC . '/post.php';
require_once ABSPATH . WPINC . '/pluggable.php';
wp_cookie_constants();
$discard = ob_get_clean();

is_user_logged_in() ||  auth_redirect();


list($basedir) = array_values(array_intersect_key(wp_upload_dir(), array('basedir' => 1)))+array(NULL);

$file = rtrim($basedir, '/') . '/' . (isset($_GET['file']) ? $_GET['file'] : '');
$file = realpath($file);

if ($file === FALSE || !$basedir || !is_file($file)) {
    status_header(404);
    die('404 &#8212; File not found.');
}

if (strpos($file, $basedir) !== 0) {
    status_header(403);
    die('403 &#8212; Access denied.');
}


$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' ];
else
    $mimetype = 'image/' . substr( $file, strrpos( $file, '.' ) + 1 );
header( 'Content-Type: ' . $mimetype ); // always send this
if ( false === strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS' ) )
    header( 'Content-Length: ' . filesize( $file ) );
$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' );
// Support for Conditional GET
$client_etag = isset( $_SERVER['HTTP_IF_NONE_MATCH'] ) ? stripslashes( $_SERVER['HTTP_IF_NONE_MATCH'] ) : false;
if( ! isset( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) )
    $_SERVER['HTTP_IF_MODIFIED_SINCE'] = false;
$client_last_modified = trim( $_SERVER['HTTP_IF_MODIFIED_SINCE'] );
// If string is empty, return 0. If not, attempt to parse into a timestamp
$client_modified_timestamp = $client_last_modified ? strtotime( $client_last_modified ) : 0;
// Make a timestamp for our most recent modification...
$modified_timestamp = strtotime($last_modified);
if ( ( $client_last_modified && $client_etag )
    ? ( ( $client_modified_timestamp >= $modified_timestamp) && ( $client_etag == $etag ) )
    : ( ( $client_modified_timestamp >= $modified_timestamp) || ( $client_etag == $etag ) )
    ) {
    status_header( 304 );
    exit;
}
// If we made it this far, just serve the file
readfile( $file );
php wordpress .htaccess
2个回答
1
投票

步骤1:

将以下内容添加到所有子域的“.htaccess”中。

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s

RewriteCond %{QUERY_STRING} !key=(FgTyUeL)
RewriteRule ^(.*)$ http://www.example.com/?dwnld_file=server1/$1 [QSA,L]

在上面的代码中,我们将所有文件重定向到主域,除非post参数设置。例如,http://server1.example.com/file.pdf将被重定向到http://www.example.com/?dwnld_file=server1/file.pdf。这里server1是您的子域名,以便识别是否有多个子域名。

在重写条件 - RewriteCond %{QUERY_STRING} !key=(FgTyUeL)key及其值FgTyUeL应保密,并随意更改为更复杂的字符串。我们将使用它来访问WordPress中的文件。

第2步:

将这些添加到您主题的主域的'functions.php'中。

/* init hook to check whether user logged-in and pass to download function */
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( 'http://www.example.com/login' ); // or some other page
            exit;
        }
        else {
            $spliturl = explode("/",$_REQUEST[ 'dwnld_file' ]);
            $originalurl = "http://".$spliturl[0].".example.com/".substr($_REQUEST[ 'dwnld_file' ], strpos($_REQUEST[ 'dwnld_file' ], "/") + 1);                
            check_download_file( $originalurl ); // if logged-in pass file to download
        }
    }
}

/* function to download file */
function check_download_file( $url ) {
    $key='?key=FgTyUeL'; // secure post key same as .htaccess
    $file = basename($url);
    $mime = wp_check_filetype( $file ); 

    if( false === $mime[ 'type' ] && function_exists( 'mime_content_type' ) )
        $mime[ 'type' ] = mime_content_type( $file );

    if( $mime[ 'type' ] )
    {           
        set_time_limit(0);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url.$key);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        $curl_response = curl_exec($ch);

        curl_close($ch);
        header('Expires: 0'); // no cache
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
        header('Cache-Control: private', false);
        header('Content-Type: application/force-download');
        header('Content-Disposition: attachment; filename="' . basename($url) . '"');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . strlen($curl_response)); // provide file size
        header('Connection: close');
        echo $curl_response;
        die();            
    }
}

上述功能不言自明 - 我们正在检查WordPress身份验证,如果登录用户,我们将附加安全密钥并使用cURL下载文件。请注意,安全密钥应与子域的“.htaccess”文件中的密钥相同。

如果文件位于子域的任何文件夹中,甚至跨越不同的域(但应该可公开访问),则上述逻辑将起作用。


1
投票

将受保护的文件放在网站公共可访问区域之外的私人文件夹中。然后,创建一个下载页面,其中包含url中的文件名或其他内容。然后在该页面上,进行身份验证:

is_user_logged_in() ||  auth_redirect();
// open file
// send headers
// echo contents
© www.soinside.com 2019 - 2024. All rights reserved.