各位观众老爷,大家好!我是今天的讲师,代号“零误差”。今天咱们来聊聊WordPress里一个看似简单,实则暗藏玄机的函数:wp_safe_redirect()
。
这玩意儿,说白了就是个“安全版”的 header('Location: ...')
。但是!它比直接用 header()
多了一层保护,防止你一不小心把用户重定向到恶意网站,导致菊花不保(数据安全,懂的都懂)。
咱们今天重点不是讲它怎么用,而是深入扒一扒它的源码,看看它是如何通过 wp_redirect_location
过滤器,让开发者能够自定义重定向白名单,让安全更有弹性。
第一幕:wp_safe_redirect()
的核心逻辑
首先,咱们先来看看 wp_safe_redirect()
的源码(为了方便讲解,我做了一些简化,只保留核心部分):
function wp_safe_redirect( $location, $status = 302 ) {
$location = wp_sanitize_redirect( $location ); // 第一道防线:清理location
if ( ! wp_is_safe_redirect( $location ) ) { // 第二道防线:安全检查
$location = wp_get_referer(); // 重定向到来源页,防止恶意跳转
if ( ! $location ) {
$location = home_url(); // 实在不行,重定向到首页
}
}
wp_redirect( $location, $status );
exit;
}
从代码里,我们可以看到几个关键步骤:
wp_sanitize_redirect( $location )
: 这是一个“预处理”函数,负责清理location
变量,防止注入攻击。它会移除一些危险字符,确保location
是一个相对安全的 URL。wp_is_safe_redirect( $location )
: 这是整个安全机制的核心。它负责判断location
是否在一个允许的白名单里。如果不在白名单里,就认为是不安全的重定向。- 备选方案: 如果
location
不安全,就尝试重定向到用户之前的页面 (wp_get_referer()
),如果连之前的页面也找不到,那就直接重定向到网站首页 (home_url()
)。 wp_redirect( $location, $status )
: 如果location
通过了安全检查,就执行真正的重定向操作。exit;
: 重定向之后,一定要终止脚本执行,防止后续代码继续运行,造成不可预知的错误。
第二幕:wp_is_safe_redirect()
的白名单机制
接下来,咱们重点看看 wp_is_safe_redirect()
这个函数。它才是决定重定向是否安全的“裁判”。
function wp_is_safe_redirect( $location ) {
$home = get_option( 'home' );
$siteurl = get_option( 'siteurl' );
$is_safe = false;
// 1. 检查是否为空
if ( empty( $location ) ) {
return false;
}
// 2. 检查是否是站内链接
if ( wp_http_validate_url( $location ) ) {
$home_url_host = parse_url( $home, PHP_URL_HOST );
$siteurl_host = parse_url( $siteurl, PHP_URL_HOST );
$location_host = parse_url( $location, PHP_URL_HOST );
if ( $location_host === $home_url_host || $location_host === $siteurl_host) {
$is_safe = true;
} else {
$is_safe = false;
}
} else {
// 相对路径,认为是安全的
$is_safe = true;
}
/**
* Filters whether the redirect location is safe.
*
* @since 3.0.0
*
* @param bool $is_safe Whether the redirect location is safe.
* @param string $location The redirect location.
*/
return apply_filters( 'wp_safe_redirect_location', $is_safe, $location );
}
这个函数的大致逻辑是:
- 获取站点 URL: 先获取网站的
home
和siteurl
选项,这两个选项通常指向你的网站域名。 - 判断是否为空: 如果
location
是空字符串, 直接返回false。 - 判断是否是站内链接: 使用
wp_http_validate_url()
判断location
是否是一个完整的 URL。如果是,就比较location
的域名和站点域名是否一致。如果一致,就认为是安全的。 - 相对路径: 如果
location
不是一个完整的 URL,而是相对路径,就认为是安全的。 wp_safe_redirect_location
过滤器: 最后,也是最重要的,使用apply_filters()
应用wp_safe_redirect_location
过滤器。这个过滤器允许开发者自定义重定向白名单,覆盖默认的安全判断逻辑。
第三幕:wp_redirect_location
过滤器的妙用
现在,咱们来重点说说 wp_redirect_location
过滤器。这玩意儿才是今天的主角!
这个过滤器允许你编写自己的函数,来判断 location
是否安全。你的函数会接收两个参数:
$is_safe
:一个布尔值,表示 WordPress 默认的安全判断结果。$location
:要重定向的 URL。
你的函数可以根据 $location
的值,返回 true
(安全) 或 false
(不安全),覆盖 WordPress 默认的判断逻辑。
举个例子,假设你想允许重定向到特定的几个外部域名,比如 example.com
和 example.org
。你可以这样写:
add_filter( 'wp_safe_redirect_location', 'my_custom_safe_redirect', 10, 2 );
function my_custom_safe_redirect( $is_safe, $location ) {
$allowed_domains = array(
'example.com',
'example.org',
);
$location_host = parse_url( $location, PHP_URL_HOST );
if ( in_array( $location_host, $allowed_domains, true ) ) {
return true; // 允许重定向到 example.com 和 example.org
}
return $is_safe; // 其他情况,沿用 WordPress 默认的安全判断
}
这段代码做了什么?
add_filter()
: 首先,使用add_filter()
注册一个过滤器,将my_custom_safe_redirect()
函数绑定到wp_safe_redirect_location
过滤器上。'wp_safe_redirect_location'
:过滤器名称。'my_custom_safe_redirect'
:你的自定义函数名称。10
:优先级,数值越小,优先级越高。2
:参数数量,表示你的函数会接收两个参数 ($is_safe
和$location
)。
my_custom_safe_redirect()
: 这是你的自定义函数。- 定义白名单: 首先,定义一个
$allowed_domains
数组,包含你允许重定向的域名。 - 解析域名: 使用
parse_url()
函数解析$location
,获取它的域名。 - 判断是否在白名单里: 使用
in_array()
函数判断$location
的域名是否在$allowed_domains
数组里。如果在,就返回true
,允许重定向。 - 沿用默认判断: 如果
$location
的域名不在白名单里,就返回$is_safe
,沿用 WordPress 默认的安全判断逻辑。
- 定义白名单: 首先,定义一个
表格总结:wp_safe_redirect_location
过滤器参数
参数名称 | 数据类型 | 描述 | ——– | ——– | ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————–0x1103702222 |
---|