在2个WordPress上共享用户安装在同一服务器上的2个子域中

Gau*_*rav 5 php cookies wordpress

我在2个不同的子域中有2个WordPress站点,如test1.abc.comtest2.abc.com.这两个站点都激活了wp-require插件,只有登录用户才能看到该站点.我们想建立一个系统,如果用户登录到一个站点,他应该自动登录到另一个站点.

我尝试了什么:

经过一番搜索,我知道我需要为两个站点使用一个数据库.所以我完成了以下步骤:

我已经下载了test2.abc.com网站的整个数据库,并将所有前缀wp_更改为wpmo_,将其替换为整个数据库并将其上传到第一个站点的数据库中.我在第二个站点的wp-config.php中添加了这两行,以定义第二个站点应该使用第一个站点的用户表而不是它自己的用户表.

define('CUSTOM_USERMETA_TABLE', 'wp_usermeta');
define('CUSTOM_USER_TABLE', 'wp_users');
Run Code Online (Sandbox Code Playgroud)

现在,第二个站点正在使用第一个站点的用户,我可以通过第一个站点的用户详细信息登录到第二个站点.

下一个问题是cookie,所以我在两个站点的wp-config中添加了这些行.

define('COOKIE_DOMAIN', '.abc.com');
define('COOKIEPATH', '/');
define('COOKIEHASH', 'aee53c017c29dc0d3ae37253fc8cbfd8');
Run Code Online (Sandbox Code Playgroud)

现在我登录test1.abc.com,当我去test2.abc.com时,它要求我登录.这意味着cookie不会从第一个站点传递到第二个站点.但是,我试图打印$ _COOKIE并且它给了我相同的加密值,但用户仍然没有在第二个站点上自动登录.当我回到第一个网站时,它会自动注销.我觉得这两个网站都在某种程度上与cookie有关,我很接近,但仍未达到我自动登录第二个网站的目标.

有帮助吗?

方案:

在Mikk3lRo和其他人的帮助下,我设法解决了这个问题.我正在为面临同样问题的任何人发布解决方案.在这里你可以找到分步指南:

步骤1:为两个安装使用一个数据库,在安装时使用2个不同的前缀安装2个wp.

步骤2:确保wp-config.php文件中随机生成的密钥和salt也相同.

步骤3:将这两行粘贴到第二个站点的wp-config.php中.

//Share user tables
define('CUSTOM_USER_META_TABLE', 'SITE1_PREFIX_usermeta');
define('CUSTOM_USER_TABLE', 'SITE1_PREFIX_users');
Run Code Online (Sandbox Code Playgroud)

第4步:与这些行共享cookie.(用wp-config.php写)

//Share cookies
define('COOKIE_DOMAIN', '.abc.com');
define('COOKIEHASH', 'aee53c017c29dc0d3ae37253fc8cbfd8');
Run Code Online (Sandbox Code Playgroud)

第5步:现在,您可以在登录第一个站点时自动登录第二个站点.但你会在第二个网站上发出错误信息"你没有权限访问这个页面",这是一件好事.

步骤6:原因是,WordPress检查用户功能(wp-includes/capabilities.php),因此您可以直接在数据库中添加此功能(如果您只有少量用户)或为此编写插件.@ Mikk3lRo在评论中写了一个插件,这很好.

谢谢

Mik*_*lRo 5

好吧-您已经很接近了,但是还有很多事情要做。

所有要求如下:

  • 使用不同的前缀共享同一数据库-您已完成此操作。从这里开始,我假设前缀为wp1_wp2_依此类推。
  • 共享wp1_userswp1_usermeta表-您已完成此操作-实际上,如果仅正确拼写了常量名称,那么您将克服了这一障碍…… CUSTOM_USER_META_TABLE(比您的下划线多一个下划线)
  • 使用通用COOKIE_DOMAINCOOKIEHASH- 在子域之间共享Cookie- 您已完成此操作
  • 确保(正常情况下)随机生成的秘密密钥和盐也相同-您没有写过这样做的信息,但从结果来看,我认为您拥有或密钥为空(这不好,但会起作用)
  • 确保prefix_capabilities共享usermeta表中每个站点的每个用户都有一个条目-我认为您没有这样做,仅仅是因为您还没有意识到自己有必要。

完整的解决方案:

这进去了wp-config.php

//Share user tables
define('CUSTOM_USER_META_TABLE', 'wp1_usermeta');
define('CUSTOM_USER_TABLE', 'wp1_users');

//Share cookies
define('COOKIE_DOMAIN', '.abc.com');
define('COOKIEHASH', 'aee53c017c29dc0d3ae37253fc8cbfd8');

/**
 * In my case these are not needed - but they may well be if one
 * of the installs is located in a sub-folder. I have not tested
 * this theory though.
 */
//define('COOKIEPATH', '/');
//define('SITECOOKIEPATH', '/');
//define('ADMIN_COOKIE_PATH', '/wp-admin');

//These all need to be identical
define('AUTH_KEY', 'this should be random');
define('SECURE_AUTH_KEY', 'this should also be a random string');
define('LOGGED_IN_KEY', 'one more random string');
define('AUTH_SALT', 'oh my - so many random strings');
define('SECURE_AUTH_SALT', 'salt, salt, salt and no eggs');
define('LOGGED_IN_SALT', 'this is sooooo random');

/**
 * These do not need to be shared - in fact they probably shouldn't be
 * - if they are you could (in theory) do actions on one site that was
 * intended for the other - probably not a very big concern in reality
 */
define('NONCE_KEY', 'these should be random too, but can differ');
define('NONCE_SALT', 'one site has one, the other another');
Run Code Online (Sandbox Code Playgroud)

这足以让您在两个站点上登录-但是列表上还剩下最后一个令人讨厌的项目符号。

问题是您的权限(“功能”)仅在其中一个站点上有效,因为的meta_key前缀是站点的表前缀。如果您在Google上搜索了一些,就会发现很多解决方案,建议您修改它们wp-includes/capabilities.php以使用通用前缀代替-我强烈建议您不要使用它!(不是出于安全原因,而是因为您将需要在每次更新后进行此补丁/修改……并且修改核心文件只是愚蠢的错误做法)

而是要纠正此障碍,您需要复制表中的wp1_capabilitieswp1_usermeta(对于每个用户!),为其添加一个新行,umeta_idwp1_wp2_meta_key列中的表前缀替换。您需要对每个站点都执行此操作,因此,您必须有一排带有meta_key wp1_capabilities,一排带有wp2_capabilities等等。

如果您和您的朋友是唯一会登录到该网站的用户,则只需通过phpMyAdmin或其他方式手动进行操作-如果您需要它动态运行,则应该可以自动使用小插件(请参见下面的编辑)。

我一直讨厌这种设计-表格前缀在表格行中没有任何作用!我认为多站点安装需要它,尽管我敢肯定会有其他(更好)的方法来解决它...

更新:插件以使用户角色在所有站点之间保持同步

usermeta创建或编辑用户时,此简单插件将重复并保持表中所需的行更新。

值得注意的一件事是它可能不适用于多站点安装,因为它们具有一些特殊的功能/角色。我还没有测试。

它可能需要针对特定​​用例进行细化(请发表评论),但对于我的有限测试用例(仅包含几个用户),它的工作就很好。对于拥有数千名用户的网站而言,这将是低效的,但由于它仅在修改用户后才运行,并且仅在需要时进行更新,我怀疑这将是一个主要问题。但是,仅阅读和修改刚刚添加/编辑的用户应该相对容易。但是,这将使初始设置有些复杂,因为先前存在的用户在第一次运行时不会自动获得重复。

创建文件夹wp-content/plugins/duplicate-caps并在其中放入以下内容duplicate-caps.php-不要忘了plugins在wordpress admin中激活它。它需要安装在所有站点上。

<?php
/*
Plugin Name: Duplicate Caps
Plugin URI: 
Description: Tiny plugin to duplicate capabilities in a setup where users (and user tables) are shared across more than one install
Author: Mikk3lRo
Version: 0.1
Author URI: 
*/
$dummy = new duplicate_caps();
class duplicate_caps {
    function __construct() {
        add_action('updated_user_meta', array($this, 'update_prefixed_caps'), 10, 2);
        add_action('added_user_meta', array($this, 'update_prefixed_caps'), 10, 2);
        add_action('deleted_user_meta', array($this, 'update_prefixed_caps'), 10, 2);
    }
    function update_prefixed_caps($mid, $object_id) {
        /**
         * Note that $object_id contains the id of the user that was
         * just changed.
         * On a site with many users it would make sense to only
         * get and set information regarding the just-changed user
         * Currently this function corrects roles for all users
         * making sure pre-existing users are duplicated, and keeping
         * the table in sync.
         */
        global $wpdb;
        //Quick and dirty - get all *capabilities rows for all users
        $sql = "SELECT * FROM {$wpdb->usermeta} WHERE `meta_key` LIKE '%capabilities'";
        $results = $wpdb->get_results($sql) or die(mysql_error());

        //Will hold all prefixes (always include our own)
        $prefixes = array($wpdb->prefix);

        //Will grab the existing role for each prefix
        $user_roles = array();

        //Loop our results
        foreach ($results as $result) {
            //Make sure the meta_key looks right, and grab the prefix
            if (preg_match('#^(.*)capabilities$#', $result->meta_key, $matches)) {
                $prefix = $matches[1];

                // Collect prefixes
                $prefixes[] = $prefix;

                //Note the entire row for later use
                $user_roles[$result->user_id][$prefix] = $result;
            }
        }

        //Make sure we only have one of each
        $prefixes = array_unique($prefixes);

        //Loop through the users we found
        foreach ($user_roles as $user_id => $existing_prefixes) {
            if (!isset($existing_prefixes[$wpdb->prefix])) {
                //User was probably just deleted - all rows are deleted by
                //wordpress though, so no cleanup for us :)
            } else {
                //We want all prefixes to obey us (we just created or changed
                //the user, so we want that to affect all sites)
                $desired_role = $existing_prefixes[$wpdb->prefix]->meta_value;

                //Loop through all prefixes
                foreach ($prefixes as $prefix) {
                    //Data to be inserted / updated
                    $cap_data = array(
                        'user_id' => $user_id,
                        'meta_key' => $prefix . 'capabilities',
                        'meta_value' => $desired_role
                    );

                    //If the prefix doesn't exist for this user
                    if (!in_array($prefix, array_keys($existing_prefixes))) {
                        //Actually insert it (user was probably just created)
                        $wpdb->insert($wpdb->usermeta, $cap_data, array('%d', '%s', '%s'));
                    } else if ($desired_role !== $existing_prefixes[$prefix]->meta_value) {
                        //Update it if not already correct (user was probably just edited)
                        $cap_data['umeta_id'] = $existing_prefixes[$prefix]->umeta_id;
                        $wpdb->replace($wpdb->usermeta, $cap_data, array('%d', '%s', '%s', '%d'));
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


dee*_*epy 2

我相信对您来说最简单的解决方案是使用 WordPress 的单点登录 (SSO) 插件之一。

这里列出了大量的插件。

您可以使用其中之一或基于其中之一进行身份验证。

或者,还有多站点可让您创建站点网络,如果您决定创建多站点,请先阅读内容。

  • 您描述的功能是单点登录 (SSO),您确定没有一个插件适合吗? (2认同)