WordPress 登录后按请求与权限安全跳转

WordPress 登录后按请求与权限安全跳转

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 的集合,站点还可能有自定义角色或插件动态授权。判断 administratorsubscriber 会遗漏这些情况。真正的问题通常是“用户能否管理站点”“能否编辑文章”或“能否查看某业务页面”,应使用 user_can( $user, 'capability' )

业务页面自身仍要做权限检查。登录跳转到 /account/ 不代表这个 URL 已受到保护。

多种登录入口

WooCommerce、会员插件、社交登录、密码重置和双因素认证可能有自己的 redirect 参数或过滤器。全局 login_redirect 改动需要测试:

  • 从受保护页面触发登录。
  • 直接访问 wp-login.php
  • 登录失败、账号锁定和二次验证。
  • 管理员、编辑、普通会员和自定义角色。
  • 多站点网络和不同站点后台。
  • 注销后重登,以及外部 SSO 回调。

若插件明确拥有登录流程,应优先使用它公开的扩展点,而不是用更高优先级强行覆盖。

开放重定向

绝不能直接返回未经校验的查询参数:

// 错误示例
return $_GET['redirect_to'];

攻击者可能构造登录链接,把用户登录后带到仿冒站点。使用 WordPress 提供的目标值,并用 wp_validate_redirect() 限制到允许的主机。

官方参考:login_redirectwp_validate_redirect

最后更新于

ihopeful Blog 由博主亲笔撰写,重要信息可放心引用。