WordPress WooCommerce数字产品仅付费用户可下载功能故障求助
解决WooCommerce付费用户专属PDF下载权限问题
一、修复下载链接权限漏洞
你当前代码直接输出了文件的原始URL,这就是任何人都能直接访问的核心问题。应该改用WooCommerce内置的带权限校验的临时下载链接,替换直接调用$each_download["file"]的写法:
修改后的代码:
if (wc_customer_bought_product('', get_current_user_id(), $product->get_id())) { $downloads = $product->get_downloads(); foreach ($downloads as $key => $each_download) { // 使用WooCommerce内置方法生成带权限的临时下载链接 $download_url = $each_download->get_download_url(); echo '<a href="' . esc_url($download_url) . '" class="btn btn-primary px-3" download> <strong class="ps-2" style="vertical-align:bottom">Download</strong></a>'; } }
这个方法生成的链接包含临时令牌,只有购买过该产品的用户才能通过链接下载,且令牌会自动过期,避免链接被随意分享传播。
二、解决Force downloads模式下的403错误
开启Force downloads后出现403,大概率是服务器配置或文件权限问题,按以下步骤排查修复:
- 检查文件目录权限:确保
wp-content/uploads/woocommerce_uploads目录权限设为755,目录内的PDF文件权限设为644,避免服务器拒绝PHP读取文件。 - 调整PHP配置:检查PHP的
open_basedir设置,如果限制了访问路径,需要把wp-content/uploads/woocommerce_uploads添加到允许列表中。 - 修复.htaccess规则:WooCommerce在Force downloads模式下需要绕过静态文件的直接访问限制,确保
woocommerce_uploads目录下的.htaccess包含以下规则(无则新建):
<FilesMatch "\.(pdf)$"> Order Allow,Deny Deny from all </FilesMatch>
该规则会禁止直接访问PDF文件,只能通过WooCommerce的权限校验接口下载。
三、额外加固方案(可选)
如果想更彻底地防止文件被直接访问,可以把数字产品文件存储在网站根目录以外的私有位置,通过自定义PHP脚本实现下载:
- 将PDF文件移到网站根目录外的目录(比如
/var/private_downloads/)。 - 在主题的
functions.php中添加自定义下载端点:
add_action('init', 'custom_pdf_download_endpoint'); function custom_pdf_download_endpoint() { add_rewrite_rule('^download-pdf/([0-9]+)/?$', 'index.php?action=custom_pdf_download&product_id=$matches[1]', 'top'); } add_action('template_redirect', 'custom_pdf_download_handler'); function custom_pdf_download_handler() { if (isset($_GET['action']) && $_GET['action'] === 'custom_pdf_download' && isset($_GET['product_id'])) { $product_id = intval($_GET['product_id']); $user_id = get_current_user_id(); // 校验用户是否购买过该产品 if (!wc_customer_bought_product('', $user_id, $product_id)) { wp_die('你没有权限下载该文件', '权限不足', 403); } // 定义私有目录中的文件路径 $file_path = '/var/private_downloads/product-' . $product_id . '.pdf'; $file_name = '产品名称-' . $product_id . '.pdf'; // 输出文件 if (file_exists($file_path)) { header('Content-Type: application/pdf'); header('Content-Disposition: attachment; filename="' . $file_name . '"'); header('Content-Length: ' . filesize($file_path)); readfile($file_path); exit; } else { wp_die('文件不存在', '错误', 404); } } }
- 刷新WordPress固定链接设置(设置→固定链接→保存更改),让新端点生效。
- 在下载按钮中使用这个自定义端点:
echo '<a href="' . home_url('/download-pdf/' . $product->get_id()) . '" class="btn btn-primary px-3"> <strong class="ps-2" style="vertical-align:bottom">Download</strong></a>';
这种方式完全隔绝了文件的直接访问路径,权限校验更可靠。
内容的提问来源于stack exchange,提问作者Znaneswar
相关产品推荐
相关产品推荐

