各位观众老爷,大家好!我是今天的讲师,江湖人称“代码老中医”,专治各种代码疑难杂症。今天咱们就来聊聊 WordPress 里面那个看似简单,实则暗藏玄机的 wp_get_referer()
函数。
这玩意儿,说白了,就是用来获取 HTTP_REFERER
的,但这可不是直接拿来就用那么简单。WordPress 作为全球最受欢迎的 CMS,安全性可是重中之重。所以,wp_get_referer()
在获取 HTTP_REFERER
的同时,还做了不少安全验证工作。
今天,咱就来扒一扒 wp_get_referer()
的源码,看看它到底是怎么工作的,以及我们应该如何正确地使用它。
一、什么是 HTTP_REFERER?
在深入了解 wp_get_referer()
之前,我们先简单回顾一下 HTTP_REFERER
。
HTTP_REFERER
是一个 HTTP 请求头,它包含了发起当前请求的页面的 URL。 简单来说,就是“你是从哪个页面跳转过来的?”。
举个例子:
假设你正在浏览我的博客 www.example.com
,然后点击了一个链接,跳转到了 www.google.com
。 那么,当你访问 www.google.com
时,你的浏览器会发送一个 HTTP 请求,其中就包含了 HTTP_REFERER
,它的值会是 www.example.com
。
HTTP_REFERER 的用途:
- 统计分析: 网站可以使用
HTTP_REFERER
来了解用户的来源,分析流量来源。 - 防盗链: 网站可以根据
HTTP_REFERER
来判断请求是否来自自己的网站,防止他人盗用资源。 - 用户体验: 某些情况下,可以根据
HTTP_REFERER
将用户重定向回之前的页面。
HTTP_REFERER 的局限性:
- 并非总是存在: 用户可以通过设置浏览器或使用某些安全工具来阻止发送
HTTP_REFERER
。 - 可能被篡改: 虽然篡改
HTTP_REFERER
比较麻烦,但理论上是可以实现的。 - 隐私问题:
HTTP_REFERER
可能会泄露用户的浏览历史,存在一定的隐私风险。
二、wp_get_referer()
的源码解析
好了,铺垫了这么多,终于要进入正题了。咱们来一起看看 wp_get_referer()
的源码,它位于 wp-includes/functions.php
文件中。为了方便阅读,我把代码简化并加上了注释:
<?php
/**
* Retrieves the referring page URL.
*
* @since 2.0.4
*
* @return string|false The referer URL if set, otherwise false.
*/
function wp_get_referer() {
$ref = '';
if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
$ref = wp_unslash( $_SERVER['HTTP_REFERER'] );
}
/**
* Filters the referer URL.
*
* @since 2.0.4
*
* @param string $ref The referer URL.
*/
return apply_filters( 'wp_get_referer', $ref );
}
是不是很简单? 别被表象迷惑了,魔鬼往往藏在细节里。
-
获取
HTTP_REFERER
:$ref = '';
首先,定义一个空字符串变量$ref
,用于存储HTTP_REFERER
的值。if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) { ... }
接着,判断$_SERVER['HTTP_REFERER']
是否为空。注意,这里使用的是! empty()
函数,它会检查变量是否存在且不为空。如果HTTP_REFERER
存在且不为空,才会执行后面的代码。$ref = wp_unslash( $_SERVER['HTTP_REFERER'] );
如果HTTP_REFERER
存在,就使用wp_unslash()
函数对其进行处理。wp_unslash()
函数的作用是移除字符串中的反斜杠。 为什么要移除反斜杠呢? 这是因为在某些情况下,服务器可能会自动在HTTP_REFERER
中添加反斜杠,为了保证数据的准确性,我们需要将其移除。 -
应用过滤器:
return apply_filters( 'wp_get_referer', $ref );
最后,使用apply_filters()
函数应用wp_get_referer
过滤器。apply_filters()
函数是 WordPress 的一个核心函数,它允许开发者通过过滤器来修改函数返回的值。 在这里,apply_filters( 'wp_get_referer', $ref )
的作用是:将$ref
的值传递给所有挂载在wp_get_referer
过滤器上的函数,这些函数可以对$ref
的值进行修改,最终apply_filters()
函数会返回修改后的$ref
值。
总结:
wp_get_referer()
函数的主要功能就是:
- 从
$_SERVER
数组中获取HTTP_REFERER
的值。 - 使用
wp_unslash()
函数移除反斜杠。 - 使用
apply_filters()
函数应用wp_get_referer
过滤器。
三、wp_safe_redirect()
和 wp_validate_redirect()
:安全重定向
光有 wp_get_referer()
还不够, WordPress 还提供了两个相关的函数,用于安全地重定向用户:
wp_safe_redirect()
wp_validate_redirect()
这两个函数可以防止恶意用户通过篡改 HTTP_REFERER
或其他方式,将用户重定向到钓鱼网站或恶意网站。
-
wp_validate_redirect()
:验证重定向 URLwp_validate_redirect()
函数的作用是验证一个 URL 是否安全,可以被用作重定向目标。它会检查 URL 是否在白名单中,或者是否是当前站点的 URL。<?php /** * Sanitizes a URL intended to be redirected to. * * Performs a number of checks for consistency. * * If the $good_protocol parameter is null, then the passed URL is checked * against the default safe protocols. * * @since 2.3.0 * * @param string $url The URL to be validated. * @param string $default The URL to redirect to if the passed URL is invalid. * @param array|null $allowed_protocols Optional. Array of acceptable protocols. * Defaults to those in wp_allowed_protocols(). * @return string The sanitized URL. */ function wp_validate_redirect( $url, $default = '' , $allowed_protocols = null ) { $url = wp_unslash( $url ); if ( ! $url ) { return $default; } $url = str_replace( ' ', '%20', $url ); $url = wp_kses_bad_protocol( $url, $allowed_protocols ); // Prevent multiple slashes from breaking the redirect. $url = str_replace( '//', '/', $url ); // Compare the normalized URL. if ( ! wp_http_validate_url( $url ) ) { return $default; } $url_parts = wp_parse_url( $url ); // Prevent open redirects to arbitrary hosts. if ( ! empty( $url_parts['host'] ) ) { $home_url_parts = wp_parse_url( home_url() ); if ( ! isset( $home_url_parts['host'] ) ) { return $default; } if ( strtolower( $url_parts['host'] ) !== strtolower( $home_url_parts['host'] ) ) { return $default; } } /** * Filters the safe redirect URL. * * @since 2.3.0 * * @param string $url The redirect URL. * @param string $default The URL to redirect to if the passed URL is invalid. */ return apply_filters( 'wp_safe_redirect_fallback', $url, $default ); }
参数说明:
$url
:要验证的 URL。$default
:如果 URL 无效,则重定向到的默认 URL。$allowed_protocols
: 允许的协议列表, 默认为wp_allowed_protocols()
返回的协议。
工作流程:
- 移除 URL 中的反斜杠,并进行URL编码
- 使用
wp_kses_bad_protocol()
函数检查 URL 是否包含恶意协议(例如javascript:
)。 - 使用
wp_http_validate_url()
函数验证 URL 的格式是否正确。 - 检查 URL 的域名是否与当前站点的域名一致。
- 应用
wp_safe_redirect_fallback
过滤器。
-
wp_safe_redirect()
:安全重定向wp_safe_redirect()
函数的作用是安全地将用户重定向到指定的 URL。 它会先使用wp_validate_redirect()
函数验证 URL 的安全性,然后再执行重定向。<?php /** * Redirects to another page. * * Performs a safe (local) redirect, using wp_redirect(). * * @since 2.1.0 * * @param string $location The path to redirect to. * @param int $status Optional. The HTTP response status code to use. Default 302 (Moved Temporarily). * @return bool False if $location is not a safe URL, otherwise true. */ function wp_safe_redirect( $location, $status = 302 ) { $location = wp_validate_redirect( $location, home_url() ); if ( ! $location ) { return false; } wp_redirect( $location, $status ); return true; }
参数说明:
$location
:要重定向到的 URL。$status
:HTTP 状态码,默认为 302(临时重定向)。
工作流程:
- 使用
wp_validate_redirect()
函数验证$location
的安全性。 如果$location
无效,则使用home_url()
作为默认的重定向 URL。 - 如果
$location
有效,则使用wp_redirect()
函数执行重定向。
四、使用示例
现在,我们来看几个使用 wp_get_referer()
、wp_validate_redirect()
和 wp_safe_redirect()
的示例。
-
获取
HTTP_REFERER
并重定向回之前的页面:<?php $referer = wp_get_referer(); if ( $referer ) { wp_safe_redirect( $referer ); exit; } else { // 如果没有 HTTP_REFERER,则重定向到首页 wp_safe_redirect( home_url() ); exit; }
在这个示例中,我们首先使用
wp_get_referer()
函数获取HTTP_REFERER
的值。 如果HTTP_REFERER
存在,则使用wp_safe_redirect()
函数将用户重定向回之前的页面。 如果HTTP_REFERER
不存在,则重定向到首页。注意: 在调用
wp_redirect()
或wp_safe_redirect()
函数后,一定要调用exit()
函数,以防止后面的代码继续执行。 -
根据
HTTP_REFERER
显示不同的内容:<?php $referer = wp_get_referer(); if ( strpos( $referer, 'www.example.com' ) !== false ) { // 如果用户来自 www.example.com,则显示特殊内容 echo '<p>欢迎来自 example.com 的朋友!</p>'; } else { // 否则,显示默认内容 echo '<p>欢迎访问本站!</p>'; }
在这个示例中,我们根据
HTTP_REFERER
的值来判断用户的来源,并显示不同的内容。 -
自定义
wp_safe_redirect()
的行为:<?php add_filter( 'wp_safe_redirect_fallback', 'my_custom_redirect_fallback', 10, 2 ); function my_custom_redirect_fallback( $url, $default ) { // 如果 URL 无效,则重定向到自定义的页面 return home_url( '/my-custom-page/' ); }
在这个示例中,我们使用
wp_safe_redirect_fallback
过滤器来修改wp_safe_redirect()
函数的行为。 如果wp_validate_redirect()
函数验证 URL 无效,则会调用my_custom_redirect_fallback()
函数,将用户重定向到自定义的页面。
五、注意事项
- 不要过度依赖
HTTP_REFERER
: 由于HTTP_REFERER
并非总是存在,并且可能被篡改,因此不要过度依赖它。 应该使用其他方式来验证用户的身份或来源。 - 始终使用
wp_safe_redirect()
函数进行重定向:wp_safe_redirect()
函数可以防止恶意用户将用户重定向到钓鱼网站或恶意网站。 - 注意隐私问题:
HTTP_REFERER
可能会泄露用户的浏览历史,因此在使用时需要注意隐私问题。 可以考虑使用其他方式来跟踪用户的来源,例如使用 UTM 参数。 - 理解
wp_validate_redirect()
函数的工作原理:wp_validate_redirect()
函数是保证重定向安全的关键。 了解它的工作原理,可以帮助你更好地保护你的网站和用户。
六、总结
wp_get_referer()
函数虽然简单,但却是 WordPress 安全体系中的重要一环。 通过它,我们可以获取 HTTP_REFERER
,并使用 wp_validate_redirect()
和 wp_safe_redirect()
函数进行安全重定向。
希望通过今天的讲解,大家能够更深入地理解 wp_get_referer()
函数的源码和使用方法,并在实际开发中正确地使用它,确保你的 WordPress 网站的安全。
今天的讲座就到这里,谢谢大家! 如果大家还有什么疑问,欢迎在评论区留言。