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

2024-05-28

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

我尝试什么:

经过一番搜索后,我知道我需要为两个站点使用一个数据库。所以我做了这些步骤:

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

define('CUSTOM_USERMETA_TABLE', 'wp_usermeta');
define('CUSTOM_USER_TABLE', 'wp_users');

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

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

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

现在我登录了 test1.abc.com ,当我访问 test2.abc.com 时,它要求我登录。这意味着 cookie 不会从第一个站点传递到第二个站点。但是,我尝试打印 $_COOKIE,它给了我相同的加密值,但用户仍然无法在第二个站点上自动登录。当我回到第一个站点时,它也会自动注销。我觉得这两个网站在 cookies 上都有关联,我已经很接近了,但仍然没有达到自动登录第二个网站的目标。

有什么帮助吗?

解决方案 :

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

step 1:两种安装均使用一个数据库,在安装时使用 2 个不同的前缀来安装 2 个 wp。

step 2:确保两个 wp-config.php 文件中随机生成的密钥和盐也相同。

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

//Share user tables
define('CUSTOM_USER_META_TABLE', 'SITE1_PREFIX_usermeta');
define('CUSTOM_USER_TABLE', 'SITE1_PREFIX_users');

step 4:与这些线路共享 cookie。 (写在wp-config.php中)

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

step 5:现在,您在登录第一个站点时将能够自动登录第二个站点。但您会在第二个站点上看到错误消息“您无权访问此页面”,这是一件好事。

step 6:原因是,WordPress 会检查用户能力(wp-includes/capability.php),因此您要么直接在数据库中添加此功能(如果您只有很少的用户),要么为此编写一个插件。 @Mikk3lRo 在评论中为此编写了一个插件,这很好。

Thanks


好吧 - 你已经很接近了,但还有一些事情要做。

所有要求如下:

  • 使用不同的前缀共享同一个数据库 - 您已经做到了。从这里我假设前缀是wp1_, wp2_等等。
  • 分享wp1_users and wp1_usermeta表 - 你已经做到了这一点 - 实际上,如果你正确拼写了常量名称,你就可以克服这个障碍......CUSTOM_USER_META_TABLE(比你所拥有的多一个下划线)
  • 使用通用方法在子域之间共享 cookieCOOKIE_DOMAIN and COOKIEHASH- 你已经做到了
  • 确保(通常)随机生成的密钥和盐也是相同的 - 您不会写下您已经完成了此操作,但根据您的结果判断,我认为您要么拥有密钥,要么您的密钥为空(这不好,但会起作用)
  • 确保有一个prefix_capabilities共享中每个站点的每个用户的条目usermetatable - 我认为您还没有这样做,只是因为您还没有达到意识到有必要这样做的程度。

完整的解决方案:

这进入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');

这足以让您登录两个站点 - 但列表中仍然剩下最后一个烦人的项目符号。

问题是您的权限(“能力”)仅在其中一个站点上有效,因为meta_key以站点的表前缀为前缀。如果你谷歌一下,你会发现很多建议修改的解决方案wp-includes/capabilities.php只使用通用前缀 - 我强烈建议不要这样做! (不是出于安全原因,而是因为您需要在每次更新后制作此补丁/破解......并且修改核心文件是非常糟糕的做法)

相反,要解决这个障碍,您需要复制wp1_capabilities行中wp1_usermeta表(对于每个用户!),给它一个新的umeta_id并替换表前缀wp1_ with wp2_ in the meta_key柱子。您需要为每个站点执行此操作,因此您有一行meta_key wp1_capabilities,一与wp2_capabilities等等。

如果您和您的朋友是唯一登录该网站的用户,那么只需通过 phpMyAdmin 或其他东西手动完成即可 - 如果您需要它动态工作,那么应该很可能使用小插件(见下面的编辑)。

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

更新:用于保持所有站点之间用户角色同步的插件

这个简单的插件将复制并保留所需的行usermeta创建或编辑用户时更新表。

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

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

创建文件夹wp-content/plugins/duplicate-caps并在里面放入以下内容duplicate-caps.php- 并且不要忘记在下面激活plugins在 WordPress 管理中。它需要安装在所有站点上。

<?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'));
                    }
                }
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • SetCookie 标头未存储

    我目前正在制作一个 Web 应用程序 其中 API 为 Node express js 前端为 Vue js 对于身份验证 我设置了 JWT 并通过 cookie HttpOnly 发送值 SetCookie 位于 Chrome Firef
  • 如何使用 C# 向 WordPress 发帖? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想编写一个程序 可以使用 C 通过 POST 方法将数据发布到 WordPress 我不知道该怎么做
  • Instagram 如何使用 Amazon S3?

    在将文件上传到 Amazon S3 时 我需要深入了解 Instagram 的工程 我刚刚开始使用 S3 我认为 Instagram 是一个值得效仿的好模式 因为他们每天上传数千张图片 我的应用程序有点相似 用户上传图片 可以删除自己的图片
  • PHP/MySQL:检索邻接列表模型中的单个路径

    有没有什么有效的方法可以在不限制深度的情况下根据节点的ID检索邻接列表模型中的单个路径 就像如果我有一个名为 Banana 的节点的 ID 我可以获得以下路径 Food gt Fruits gt Banana 如果不可能的话也不是什么大问题
  • 基于 PHP 的 CSV 编辑器? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有谁知道用 PHP 编写的在线 CSV 编辑器允许用户打开 编辑和保存给定的 CSV 文件 我能找到的只
  • 在 symfony2 中为特定控制器设置 max_execution_time

    Using ini set 我可以扩展最大执行时间一个脚本的 在Symfony2 我可以添加ini set to web app php and web app dev php将增加的执行时间应用于所有控制器 但在这种情况下 我只想扩展最大
  • xdebug_start_trace 行为异常

    我正在尝试进一步减少脚本内存使用量 我试图让我的脚本使用 xdebug 生成输出来分析内存使用情况 这是一个基于 CLI 的脚本 有 shebang usr local bin php q 我向它传递一个参数并检查它 argc gt 1 i
  • PHP 中的正则表达式:找到第一个匹配的字符串

    我想在非常长的文本中找到第一个匹配的字符串 我知道我可以使用 preg grep 并获取返回数组的第一个元素 但是 如果我只需要第一场比赛 或者我知道提前只有一场比赛 那么这样做效率不高 有什么建议吗 预匹配 http www php ne
  • SimpleSAMLPHP 重定向循环

    我们正在尝试使用自定义 mysql 数据库设置 sso 但它在以下两个请求之间进入无限循环 POST http 192 168 0 15 simplesaml module php core loginuserpass php 设置Cook
  • 使用 PDO 在 SQLite 中检索单个(且唯一)行的最简单方法

    我有这个 PDO stmt db gt prepare SELECT FROM channels WHERE id id stmt gt bindValue id id SQLITE3 INTEGER result stmt gt exec
  • CSV 从 UTF8 到 ISO-8859-1

    我正在尝试修改我的 CSV 导出 但它不会将我的 CSV 从 UTF 8 转换 保存为 ISO 8859 1 请问我做错了什么吗 实际上自从修改了这个之后 我得到了一个空的 CSV 文件 php 7 0 x function my Gene
  • WAMP 不显示目录列表中的图标

    过去 我通过 vmware 处理 PHP 代码 但最近我决定转而通过 WAMP 在 Windows 8 1 上 在本地进行处理 我创建了一个空文件夹tests in the www folder 然后在我的浏览器上输入http localh
  • 如何创建环境变量来保护我的网站的 Google 地图 API 密钥(或任何其他秘密值)?

    我正在学习使用 Bootstrap 编写自己的网站 并使用 Google 地图 API 密钥和 Google Developers 的脚本轻松地将地图放置在我的页面上 理想情况下 我会有类似的东西 即我已经尝试过这个 Html PHP
  • 在 MySQL 中搜索多个单词

    我使用 HTML 表单来允许用户查找数据库表中的条目
  • ZF2 工厂获取参数

    我有一个动态类别导航 在导航工厂中 我想从路线获取参数 我怎样才能做到这一点 在我看来 在我的 module php 中 public function getServiceConfig return array factories gt
  • 在 WordPress 和 woocommerce 中禁用 zxcvbn.min.js

    如您所知 zxcvbn min js 约为 400kb 并且默认在 WordPress 网站中加载 我想知道如何阻止加载此 JavaScript 库 因为我不想在我的网站中检查密码长度 将以下内容添加到主题的 function php 或自
  • 从多个选择列表中插入数据到mysql数据库(html形式)

    我制作了一个表格 其中有商店的 ID
  • $_SESSION 中保存大量信息可以吗?

    我需要存储许多数组 SESSION以防止从 MySQL 检索信息 可以吗 其中 太多 的信息有多少 SESSION还是没有 太多 谢谢 附 或者更好地使用http php net manual en book memcache php ht
  • WordPress 事件按元生效日期排序

    我在获取参数数组以按 Wordpress 中的日期对事件列表进行排序时遇到一些问题 我在 Stack Overflow 和其他地方找到了几个建议的解决方案 但经过大量的试验和错误后 这些解决方案似乎都不起作用 这没什么花哨的 而且应该比这容
  • sqlsrv_num_rows 不返回任何值

    我正在尝试获取查询中返回的行数 while 循环遍历结果有效 但由于某种原因 sqlsrv num rows 不返回任何值 result SELECT from dtable WHERE id2 apple query sqlsrv que

随机推荐