
本文详细介绍了如何解决woocommerce中未登录用户意外访问“我的账户”页面及其自定义端点的问题。通过利用`template_redirect`钩子和精确的条件逻辑,教程展示了如何确保只有已登录用户才能访问这些受保护的页面,同时允许“找回密码”等特定页面对未登录用户开放,从而提升网站的安全性和用户体验。
在WooCommerce开发中,有时我们希望“我的账户”页面及其所有子页面(包括自定义端点)仅对已登录用户可见。例如,当网站设计要求登录/注册表单以弹窗形式展示,而非通过默认的“我的账户”页面时,就需要实现这种重定向机制。这不仅关乎用户体验,更是网站安全性的重要组成部分,防止未授权访问敏感信息或功能。
理解问题:未登录用户访问“我的账户”端点
最初的重定向尝试通常会针对“我的账户”主页面进行,但往往忽略了其下方的自定义端点。当用户在未登录状态下直接访问如 my-account/my_returns 这样的自定义端点时,原有的重定向逻辑可能无法生效,导致用户看到不应出现的登录表单或页面内容。
初始重定向逻辑示例(存在局限性):
add_action( 'template_redirect', 'wish_custom_redirect' );
function wish_custom_redirect() {
global $wp;
if (
!is_user_logged_in()
&&
('my-account' == $wp->request) // 仅针对 'my-account' 主页面
&&
('lost-password' != $wp->request) // 排除 'lost-password'
)
{
wp_redirect( home_url() );
exit;
}
}
这段代码的问题在于,(‘my-account’ == $wp->request) 这一条件只精确匹配了“我的账户”主页的请求路径。当请求路径是 my-account/my_returns 时,$wp->request 的值会是 my-account/my_returns,与 ‘my-account’ 不匹配,因此重定向不会触发。
WooCommerce自定义端点的创建
为了更好地理解重定向的必要性,我们首先回顾一下WooCommerce中自定义端点的典型创建流程。这个过程涉及添加重写规则、注册查询变量、将端点添加到账户菜单以及为端点添加内容。
-
注册新的重写端点: 使用 add_rewrite_endpoint() 函数为“我的账户”页面添加一个新的URL端点。
function ts_custom_add_my_returns_endpoint() { add_rewrite_endpoint( 'my_returns', EP_ROOT | EP_PAGES ); } add_action( 'init', 'ts_custom_add_my_returns_endpoint' );登录后复制 -
添加新的查询变量: 注册与端点对应的查询变量,以便WordPress识别。
function ts_custom_my_returns_query_vars( $vars ) { $vars[] = 'my_returns'; return $vars; } add_filter( 'woocommerce_get_query_vars', 'ts_custom_my_returns_query_vars', 0 );登录后复制 -
插入到“我的账户”菜单: 将新端点添加到“我的账户”导航菜单中。
function ts_custom_add_my_returns_link_my_account( $items ) { $items['my_returns'] = 'My returns'; return $items; } add_filter( 'woocommerce_account_menu_items', 'ts_custom_add_my_returns_link_my_account' );登录后复制 -
为端点添加内容: 使用 woocommerce_account_{endpoint_slug}_endpoint 钩子为自定义端点填充内容。
function ts_custom_my_returns_content() { // 在此处添加端点页面的具体内容,例如显示退货订单列表 ?> <h2 class="text-center woocommerce-products-header__title page-title need-title"><?php echo get_theme_mod('my_returns_tab_heading') ?></h2> <section class="order"> <?php $orders = wc_get_orders( array( 'numberposts' => -1, 'orderby' => 'date', 'order' => 'DESC', 'customer_id' => get_current_user_id(), 'status' => array('refunded','cancelled'), ) ); foreach( $orders as $order ){ // ... 订单内容展示逻辑 ... } ?> </section> <?php } add_action( 'woocommerce_account_my_returns_endpoint', 'ts_custom_my_returns_content' );登录后复制注意: 在添加或修改重写规则后,务必访问WordPress后台的“设置” > “固定链接”页面,并点击“保存更改”按钮,以刷新重写规则,否则可能会出现404错误。
解决方案:扩展重定向逻辑以包含自定义端点
要正确地重定向未登录用户对“我的账户”主页面及其所有自定义端点的访问,我们需要更精细的条件判断。关键在于使用逻辑或 (||) 运算符来组合多个页面路径的匹配,同时通过逻辑与 (&&) 运算符确保用户未登录且排除特定页面。
以下是经过优化的重定向代码:
add_action('template_redirect', 'wish_custom_redirect_extended');
function wish_custom_redirect_extended()
{
global $wp; // 访问全局 $wp 对象,其中包含当前请求的路径
// 定义需要保护的账户页面端点列表
// 这里的 'my-account' 是主页,'my_returns' 是一个自定义端点
// 您可以根据需要添加更多自定义端点,例如 'my_addresses', 'edit-account' 等
$protected_endpoints = array(
'my-account',
'my-account/my_returns', // 示例自定义端点
// 添加其他需要保护的自定义端点,例如:
// 'my-account/my_wishlist',
// 'my-account/orders',
// 'my-account/edit-account',
// 'my-account/edit-address',
// 'my-account/payment-methods',
// 'my-account/customer-logout', // 通常应允许登出,但如果需要重定向也可以包含
);
// 检查当前请求路径是否在受保护的端点列表中
$is_protected_endpoint = false;
foreach ($protected_endpoints as $endpoint) {
// 匹配精确路径或以该路径开头的任何子路径
// 例如,如果 $wp->request 是 'my-account/orders/view-order/123'
// 那么 'my-account/orders' 应该匹配
if (strpos($wp->request, $endpoint) === 0) {
$is_protected_endpoint = true;
break;
}
}
// 综合判断是否需要重定向
if (
!is_user_logged_in() // 用户未登录
&&
$is_protected_endpoint // 且当前页面是受保护的账户页面或其子页面
&&
('lost-password' != $wp->request) // 排除“找回密码”页面
) {
// 使用 wp_safe_redirect() 进行安全重定向到网站首页
wp_safe_redirect(site_url());
exit; // 终止脚本执行
}
}
// 确保用户登出后也重定向到首页,防止返回缓存页面
add_action('wp_logout','auto_redirect_after_logout');
function auto_redirect_after_logout(){
wp_safe_redirect( home_url() );
exit();
}
代码解释与最佳实践
- $wp->request: 这个全局变量包含了当前请求的干净URL路径(不含域名和查询参数)。它是判断用户访问哪个页面的关键。
- !is_user_logged_in(): 这是一个WordPress核心函数,用于检查当前用户是否已登录。
-
$protected_endpoints 数组和循环:
- 我们定义了一个数组 $protected_endpoints 来列出所有需要保护的“我的账户”相关路径。这使得代码更易于维护和扩展。
- 通过循环遍历这个数组,并使用 strpos($wp->request, $endpoint) === 0 来检查当前请求路径是否以任何一个受保护的端点开头。这种方式可以捕获主端点及其所有子端点(例如,my-account 会匹配 my-account、my-account/orders 等)。
- (‘lost-password‘ != $wp->request): 这一条件至关重要,它确保“找回密码”页面对未登录用户是可访问的,这是恢复账户的必要功能。
-
wp_safe_redirect(site_url()):
- wp_safe_redirect() 是WordPress推荐的重定向函数,它比 wp_redirect() 更安全,因为它会验证重定向URL,防止开放重定向漏洞。
- site_url() 返回WordPress网站的URL,即重定向的目标地址。
- exit;: 在重定向后,务必调用 exit; 来终止脚本的进一步执行,防止在重定向发生后仍然输出其他内容。
- wp_logout 钩子: 额外添加的 wp_logout 钩子确保用户在登出后立即被重定向到网站首页,防止他们使用浏览器后退按钮返回到可能包含敏感信息的缓存页面。
实施步骤
-
选择放置位置: 将上述优化后的代码片段添加到您的主题的 functions.php 文件中。
- 推荐做法: 最好将其放置在一个子主题的 functions.php 文件中,这样在更新父主题时不会丢失您的自定义代码。
- 更专业的做法: 创建一个自定义插件来管理这类功能,这有助于代码的模块化和可移植性。
-
测试:
- 清除网站缓存(如果使用了缓存插件)。
- 使用不同的浏览器或隐身模式,在未登录状态下尝试直接访问“我的账户”主页 (/my-account/) 和您创建的自定义端点 (/my-account/my_returns/)。
- 确认这些页面都成功重定向到了网站首页。
- 测试“找回密码”页面 (/my-account/lost-password/),确保它仍然可以正常访问。
- 登录后测试,确保已登录用户可以正常访问所有“我的账户”页面和端点。
通过以上步骤和代码,您可以有效地控制WooCommerce中“我的账户”页面及其自定义端点的访问权限,确保只有已登录用户才能查看这些内容,从而提升网站的安全性和用户体验。
以上就是WooCommerce:安全重定向未登录用户的自定义账户页面端点的详细内容,更多请关注php中文网其它相关文章!


