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


sharing user on 2 WordPress installs in 2 sub domains on same server

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

我尝试什么:

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

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

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,它给了我相同的加密值,但用户仍然没有在第二个站点上自动登录。另外,当我回到第一个站点时,它会自动注销。我觉得这两个网站在 cookie 上都有某种联系,我已经接近但仍未达到自动登录第二个网站的目标。

有什么帮助吗?

溶液:

经过Mikk3lRo和其他人的一些帮助,我设法解决了这个问题。 我正在为面临相同问题的任何人发布解决方案。在这里,您可以找到分步指南:

步骤 1:对两个安装使用一个数据库,在安装时使用 2 个不同的前缀安装 2 WP。

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

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

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

第 4 步:与这些行共享 cookie .(写在WP-config.php中)

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

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

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

谢谢

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

所有要求如下:

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

完整的解决方案:

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_usermeta表中的wp1_capabilities行(对于每个用户!),给它一个新的umeta_id,并将表前缀wp1_替换为meta_key列中的wp2_。您需要为每个站点执行此操作,因此您有一行包含meta_key wp1_capabilities,一行包含wp2_capabilities,依此类推。

如果您和您的朋友是唯一会登录这些站点的用户,那么只需通过 phpMyAdmin 或其他东西手动完成 - 如果您需要它动态工作,那么应该很有可能使用一个小插件实现自动化(请参阅下面的编辑)。

我一直讨厌这种设计 - 表格前缀在表格行内没有业务!我认为多站点安装需要它,尽管我相信还有其他(更好)的方法来解决它......

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

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

值得注意的是,它可能无法与多站点安装一起使用,因为它们具有一些特殊功能/角色。我还没有测试过这个。

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

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

<?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'));
                    }
                }
            }
        }
    }
}
我相信最简单的

解决方案是使用WordPress的单点登录(SSO)插件之一。

这里列出了大量的插件。

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

或者,多站点可以让您创建站点

网络,如果您决定创建多站点,请先阅读本文。

我认为定义cookie不足以登录wp网站。

所以我的解决方案是,创建一个插件来限制那些不登录其中一个站点的人的访问。在用户登录其中一个网站时设置 cookie。当用户查看网站时。检查 Cookie 值,然后重定向或返回到网站。

示例代码:

 add_action('wp_login','prefix_set_cookie'); //when someone logged in this call the set_cookie function
 function prefix_set_cookie(){
    setcookie('hashed_cookie','my_value'); //set the cookie
 }
 //call check_cookie function when wordpress site loads
 add_action('wp','check_cookie');
 function check_cookie(){
    //check the cookie value and view the website
    if(isset($_COOKIE['hashed_cookie'] )){
        if($_COOKIE['hashed_cookie'] == 'my_value'){
         return;            
        }else{
            die("no access please login <a href='your login link'>LINK</a>");
        }
    }
 }

此插件的主要缺点是安全性差。 任何人都可以手动创建此cookie。 所以它的高安全性,不要用这个。 尝试对 cookie 进行哈希处理,使其无法轻松手动创建。

(如果你想要插件的完整代码,请放在某个地方)

更新(完整插件):

<?php
/*
Plugin Name: Restrict Access
Author: Pasindu Jayawardane
Description: This Plugin Restrict Access to the Site without login
Author URI: https://www.facebook.com/pj.pasiya
*/
 $key = hash('md5','restrict_access');
 $value = hash('md5','true');
 add_action('wp_login','es_set_cookie');
 function es_set_cookie(){
    global $key, $value;
    setcookie($key, $value ,time()+3600);
 }
 add_action('wp_logout','es_remove_cookie');
 function es_remove_cookie(){
    global $key, $value;
    setcookie($key, $value ,time()-3600);
 }
 add_action('wp','es_check_cookie');
 function es_check_cookie(){
    global $key, $value;
    if(isset($_COOKIE[$key] )){
        if($_COOKIE[$key] == $value){
         return;            
        }else{
            ?>
            <h1 class="alert alert-danger">
                This Website is Protected! <small>You Must Login to See the Website</small>
            </h1>
            <p class="ra-login"> <a href="<?php echo wp_login_url(); ?>"> Login </a> <p>
        <?php
            die();
        }
    }else{
        ?>
        <h1 class="alert alert-danger">
            This Website is Protected! <small>You Must Login to See the Website</small>
        </h1>
        <p class="ra-login"> <a href="<?php echo wp_login_url(); ?>"> Login </a> <p>
        <?php
        die();
    }
 }

转到您的WordPress安装插件目录({{WP安装文件夹}}->WP-Content->插件并创建一个.php扩展名为{{file-restrict.php}}的新文件 复制并粘贴此代码

对两个站点执行此操作

转到WordPress插件并激活该插件。(两个站点)

登录到其中一个站点

后,您可以查看其中一个站点。一旦您注销一个站点,它就会显示一条消息,其中包含登录到该站点的链接。

(激活后只需注销并登录到站点)

我也会通过电子邮件为您发送代码。