WordPress-多站点迁移本地问题记录

◆ 问题1:子站点后台登录错误:Cookies 被阻止或者您的浏览器不支持。要使用 WordPress,您必须启用 cookies。

本人站点是多站点模式,子站点登录后台时提示错误:【Cookies 被阻止或者您的浏览器不支持。要使用 WordPress,您必须启用 cookies。】,如下图。

原因分析:在 localhost 环境下,浏览器会【拒绝】 domain=.localhost 的 Cookie(不符合公共后缀规则)。

//wp-login.php
//...
setcookie( TEST_COOKIE, 'WP Cookie check', 0, COOKIEPATH, COOKIE_DOMAIN, $secure );

如上代码,setcookie() 是 PHP 内置的用于设置 COOKIE 的函数。它会向客户端(浏览器)发送一个 HTTP 头,其作用是 设置一个测试 Cookie,用于检测浏览器是否支持并接受 Cookie。这段代码通常出现在登录或身份验证流程中,以确保用户的浏览器能够正确处理 Cookie(例如,在登录时需要 Cookie 保存会话信息)。

继续分析我所发送的【 HTTP 头】,如下:

//wp-login.php
echo '<pre>';
// 获取所有 HTTP 头信息
$headers = headers_list();
// 打印 HTTP 头信息
print_r($headers);

// $headers 值为:
Array
(
    [0] => X-Powered-By: PHP/8.2.13
    [1] => Expires: Wed, 11 Jan 1984 05:00:00 GMT
    [2] => Cache-Control: no-cache, must-revalidate, max-age=0
    [3] => Content-Type: text/html; charset=UTF-8
    [4] => Set-Cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/; domain=.localhost
    [5] => X-Frame-Options: SAMEORIGIN
)

可知,我向浏览器发送Cookie 的 domain 属性正是【domain=.localhost】,导致被浏览器拒绝。因为根据 HTTP 标准,Cookie 的 domain 属性需要是【有效的公共后缀】(如 .chenzhuzhen.cn),而 localhost 是保留的本地域名,浏览器通常不会接受以 .localhost 作为域名的 Cookie。

而且,即使是【domain=localhost】,根据 HTTP 协议规范,浏览器会将 localhost 视为一个 【无点域名】导致被拒绝。

wordpress接下来会检查该 COOKIE 是否存在【 empty($_COOKIE[TEST_COOKIE]) 】,如下代码,我这个肯定是失败的。所以产生上述问题。

//wp-login.php
<?php
if (empty($_COOKIE[LOGGED_IN_COOKIE])) {
    if (headers_sent()) {
        //...
    } elseif (isset($_POST['testcookie']) && empty($_COOKIE[TEST_COOKIE])) {
        // If cookies are disabled, the user can't log in even with a valid username and password.
        $user = new WP_Error(
            'test_cookie',
            //...
        );
    }
}

解决方案:在 wp-config.php 中设置空域名,即可解决。

define('COOKIE_DOMAIN','');
define('COOKIEPATH', '/');
define('SITECOOKIEPATH', '/');

这样,wordpress发送如下Cookie 头

[4] => Set-Cookie: wordpress_test_cookie=WP%20Cookie%20check; path=/

◆ 跨子域名共享 Cookie 与 单个子域名使用 Cookie 区别

跨子域名共享 Cookie:即多个子域名之间需要共享用户登录状态等信息。要实现跨子域名的 Cookie 共享,需要将 Cookie 的域名设置为主域名,并在前面加上前导点。在本地环境中,若要让 example3.localhost 和 example4.localhost 共享 Cookie,理论上应将 COOKIE_DOMAIN 设置为 .localhost 。不过正如前面提到的,现代浏览器出于安全考虑,对以 .localhost 作为 Cookie 域名的设置较为严格,可能会拒绝该设置。在生产环境中,如果是正式域名,如 example.com,可以将 COOKIE_DOMAIN 设置为 .example.com,这样在 sub1.example.com 和 sub2.example.com 等子域名下就可以共享 Cookie 了。注意:跨子域名共享 Cookie 会增加安全风险。因为一旦某个子域名存在安全漏洞(如 XSS 攻击),攻击者就有可能获取到共享的 Cookie 信息,进而利用这些信息在其他子域名下进行非法操作。

单个子域名使用 Cookie:若仅在单个子域名(如 example3.localhost)内使用 Cookie,通常可以将 COOKIE_DOMAIN 设置为空字符串。这样 WordPress 会使用当前请求的具体域名作为 Cookie 域名,也就是 example3.localhost ,此设置符合浏览器的安全策略,能确保 Cookie 正常工作。

◆ 问题2:The requested URL was not found on this server.

首页可以打开,但是打开具体的文章内容链接时,提示:【Not Found The requested URL was not found on this server.】页面错误,如下图:

这是因为迁移时需要重新【更新】固定链接,步骤如下:【设置】->【固定链接】打开【固定链接设置页面】,无需更改【固定链接结构】,只要点击按钮【保存更改】即可。

修改.htaccess 文件重新配置web服务器重写规则

本人使用apache作为web服务器,因此需要修改【htaccess】文件来重新配置重写规则。在【我的站点】->【管理网络】->【设置】->【配置网络】里复制【.htaccess 的站点网络配置规则】里的脚本至wordpress根目录里(如果没有,则自行创建)。如下图。修改后【重启】web服务器,这时再去修改【固定链接设置页面】中任一选项,均可正常使用。

◆ 问题3:localhost 将您重定向的次数过多。

打开localhost,一直提示【localhost 将您重定向的次数过多】,其url重定向【http://localhost/wp-signup.php?new=localhost】。

调试代码,发现问题出现在以下相关该代码段。

if ( ! isset( $current_site ) || ! isset( $current_blog ) ) {
        ....

	//是 WordPress 多站点系统中的一个核心函数,其主要功能是根据传入的域名、
	//路径和多站点安装类型(子域名安装或子目录安装)来确定当前请求对应的站点和网络信息,并将这些信息加载到全局变量中,
	//以便后续代码可以使用这些信息进行相关操作。
	$bootstrap_result = ms_load_current_site_and_network( $domain, $path, is_subdomain_install() );

	if ( true === $bootstrap_result ) {
		// `$current_blog` and `$current_site are now populated.
	} elseif ( false === $bootstrap_result ) {
		ms_not_installed( $domain, $path );
	} else {
		header( 'Location: ' . $bootstrap_result );
		exit;
	}
        ....
}
	// function:ms_load_current_site_and_network()
	if ( empty( $current_blog ) ) {
		do_action( 'ms_site_not_found', $current_site, $domain, $path );
		if ( $subdomain && ! defined( 'NOBLOGREDIRECT' ) ) {
			// For a "subdomain" installation, redirect to the signup form specifically.
			$destination .= 'wp-signup.php?new=' . str_replace( '.' . $current_site->domain, '', $domain );
		} elseif ( $subdomain ) {
			/*
			 * For a "subdomain" installation, the NOBLOGREDIRECT constant
			 * can be used to avoid a redirect to the signup form.
			 * Using the ms_site_not_found action is preferred to the constant.
			 */
			if ( '%siteurl%' !== NOBLOGREDIRECT ) {
				$destination = NOBLOGREDIRECT;
			}
		} elseif ( 0 === strcasecmp( $current_site->domain, $domain ) ) {
			/*
			 * If the domain we were searching for matches the network's domain,
			 * it's no use redirecting back to ourselves -- it'll cause a loop.
			 * As we couldn't find a site, we're simply not installed.
			 */
			return false;
		}
		return $destination;
	}

具体体现:【$bootstrap_result】返回异常,【$current_blog】值为【空】。其原因是:迁移过程中,数据库里的站点信息没有正确迁移。特别是表【wp_blogs】站点信息未修改。

◆ 修改表wp_blogs站点信息

表wp_blogs 存储管理多站点信息,借助这些信息,WordPress 能够识别、定位和管理不同的站点。把字段【domain】里面改为本地地址:如:【www.chenzhuzhen.cn】改为【localhost】,如下图

修改后,再次调试,这时【$current_blog】和【$bootstrap_result】有值了,如下:

WP_Site Object
(
    [blog_id] => 1
    [domain] => localhost
    [path] => /
    [site_id] => 1
    [registered] => 2025-01-31 15:18:58
    [last_updated] => 2025-03-20 12:03:58
    [public] => 1
    [archived] => 0
    [mature] => 0
    [spam] => 0
    [deleted] => 0
    [lang_id] => 0
)