WordPress 的 login_redirect 过滤器会提供最终跳转地址、用户原始请求地址和登录结果。实现时要处理 WP_Error、避免开放重定向,并尽量保留用户登录前真正想访问的页面。
示例:管理员进入后台,普通用户进入账户页
<?php
add_filter(
'login_redirect',
function (
string $redirect_to,
string $requested_redirect_to,
$user
): string {
if (
is_wp_error( $user ) ||
! $user instanceof WP_User
) {
return $redirect_to;
}
// 优先尊重站内安全的原始目标。
$requested = wp_validate_redirect(
$requested_redirect_to,
''
);
if ( $requested ) {
return $requested;
}
if ( user_can( $user, 'manage_options' ) ) {
return admin_url();
}
return home_url( '/account/' );
},
10,
3
);
不要在过滤器中调用 wp_redirect() 或 exit,只返回 URL。WordPress 会继续处理登录流程。
为什么按 capability,而不是角色名
角色是 capability 的集合,站点还可能有自定义角色或插件动态授权。判断 administrator、subscriber 会遗漏这些情况。真正的问题通常是“用户能否管理站点”“能否编辑文章”或“能否查看某业务页面”,应使用 user_can( $user, 'capability' )。
业务页面自身仍要做权限检查。登录跳转到 /account/ 不代表这个 URL 已受到保护。
多种登录入口
WooCommerce、会员插件、社交登录、密码重置和双因素认证可能有自己的 redirect 参数或过滤器。全局 login_redirect 改动需要测试:
- 从受保护页面触发登录。
- 直接访问
wp-login.php。 - 登录失败、账号锁定和二次验证。
- 管理员、编辑、普通会员和自定义角色。
- 多站点网络和不同站点后台。
- 注销后重登,以及外部 SSO 回调。
若插件明确拥有登录流程,应优先使用它公开的扩展点,而不是用更高优先级强行覆盖。
开放重定向
绝不能直接返回未经校验的查询参数:
// 错误示例
return $_GET['redirect_to'];
攻击者可能构造登录链接,把用户登录后带到仿冒站点。使用 WordPress 提供的目标值,并用 wp_validate_redirect() 限制到允许的主机。