共享用户在同一服务器上的2个子域中的2个WordPress安装 [英] sharing user on 2 WordPress installs in 2 sub domains on same server

查看:569
本文介绍了共享用户在同一服务器上的2个子域中的2个WordPress安装的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我尝试: strong>



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



我已经下载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和其他人的帮助下,我设法解决了这个问题。我为所有面临同样问题的人发布解决方案。
在这里你可以找到一步一步的指南为这:



步骤1:使用一个数据库的两个安装,安装2 wp

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



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

  //共享用户表
define('CUSTOM_USER_META_TABLE','SITE1_PREFIX_usermeta');
define('CUSTOM_USER_TABLE','SITE1_PREFIX_users');

第4步:使用这些行分享Cookie。 (写在wp-config.php)

  //共享cookies 
define('COOKIE_DOMAIN','。 abc.com');
define('COOKIEHASH','aee53c017c29dc0d3ae37253fc8cbfd8');

第5步:您现在可以在第二个网站当登录到第一站点。但是你会在第二个网站你没有访问此网页的权限的错误消息,这是一件好事。



步骤6:原因是,WordPress检查用户能力(wp-includes / capabilities.php),所以要么直接在数据库中添加此功能(如果您只有很少的用户)或为此编写一个插件。



感谢

解决方案



所有要求如下:




  • 使用不同的前缀共享同一个数据库 - 您已经这样做了。从这里我假设前缀是 wp1 _ wp2 _ 等。

  • 分享 wp1_users wp1_usermeta 表 - 你已经做到了 - 实际上你会克服这个障碍,如果只有您已正确拼写常数名称... CUSTOM_USER_META_TABLE (再加一个下划线)

  • 在子域之间共享Cookie使用公共 COOKIE_DOMAIN COOKIEHASH - 您已完成此操作

  • 确保(通常)随机生成的密钥和盐也是相同的 - 你不写你做了这个,但根据你的结果判断,我认为你有或你的密钥是空的(这是不好的,但将工作)

  • 确保共享中每个站点的每个用户都有 prefix_capabilities 条目 usermeta table - 我不认为你已经做到了,只是因为你还没有达到你意识到这一点的必要。



完成解决方案:



这将进入 wp-config.php



  //共享用户表
define('CUSTOM_USER_META_TABLE','wp1_usermeta');
define('CUSTOM_USER_TABLE','wp1_users');

//分享Cookie
define('COOKIE_DOMAIN','.abc.com');
define('COOKIEHASH','aee53c017c29dc0d3ae37253fc8cbfd8');

/ **
在我的例子中,这些不需要 - 但是如果一个
*的安装位于一个子文件夹中。我没有测试过
*这个理论。
* /
// define('COOKIEPATH','/');
// define('SITECOOKIEPATH','/');
// define('ADMIN_COOKIE_PATH','/ wp-admin');

//这些都需要是相同的
define('AUTH_KEY','这应该是随机的');
define('SECURE_AUTH_KEY','这也应该是一个随机字符串');
define('LOGGED_IN_KEY','one more random string');
define('AUTH_SALT','oh my - 这么多随机字符串');
define('SECURE_AUTH_SALT','盐,盐,盐和没有鸡蛋');
define('LOGGED_IN_SALT','this is sooooo random');

/ **
*这些不需要共享 - 其实他们可能不应该是
* - 如果他们是你可以(理论上)做行动一个网站是
*用于另一个 - 可能不是一个非常大的关注现实
* /
define('NONCE_KEY','这些应该是随机的,但可以不同') ;
define('NONCE_SALT','一个网站有一个,另一个');

这足够让你在两个网站上登录 - 但仍然有最后一个烦人的项目符号问题是你的权限(功能)只在一个网站上有效,因为 meta_key 以站点的表前缀为前缀。如果你google了一下,你会发现许多解决方案建议修改 wp-includes / capabilities.php 只使用一个共同的前缀 - 我强烈建议反对! (不是出于安全原因,但是因为你需要在每次更新后修改这个补丁/修改...而且修改核心文件只是疯狂的做法)



要修复此障碍,您需要复制 wp1_usermeta 表中的 wp1_capabilities 行(对于每个用户!), a umeta_id 并用 wp2 _ 替换表前缀 wp1 _ meta_key 列中。您需要为每个网站执行此操作,所以您有一行 meta_key wp1_capabilities



如果您和您的朋友是唯一可以登录网站的用户,然后只需通过phpMyAdmin或某些事情 - 如果你需要它的工作动态,那么应该是很可能的自动化一个小插件(见下面的编辑)。



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



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



这个简单的插件会复制并保留用户在 usermeta 创建或编辑。



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



它可能需要细化的特定用例(请做评论),但它的工作罚款我的有限的测试用例,只包括很少用户。对于具有数千个用户的站点来说,这将是低效率的,但是它仅在用户被修改时运行,并且仅当需要时才进行更新我怀疑这将是一个主要关注点。但是,它应该相对容易适应只读和修改刚刚添加/编辑的用户。



创建文件夹 wp- content / plugins / duplicate-caps 和里面放置 duplicate-caps.php 中的以下内容,并且不要忘记激活 plugins 在wordpress admin。

 <?php 
/ *
插件名称:重复大写
插件URI:
描述:Tiny插件在一个设置中重复的功能,其中用户(和用户表)在多个安装之间共享
作者:Mikk3lRo
版本: 0.1
作者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){
/ **
*请注意,$ object_id包含的用户的id是
*刚刚更改。
*在许多用户的网站上,只有
*获取和设置刚更改的用户的信息是有意义的
*目前此函数更正所有用户的角色
*确保预先存在的用户重复,并保持
*表同步。
* /
global $ wpdb;
//快速和脏 - 为所有用户获取所有*能力行
$ sql =SELECT * FROM {$ wpdb-> usermeta} WHERE`meta_key` LIKE'%capabilities'
$ results = $ wpdb-> get_results($ sql)或die(mysql_error());

//将保存所有前缀(始终包括我们自己的)
$ prefixes = array($ wpdb-> prefix);

//将获取每个前缀的现有角色
$ user_roles = array();

//循环我们的结果
foreach($ results as $ result){
//确保meta_key看起来正确,并抓取前缀
if(preg_match ('#^(。*)capabilities $#',$ result-> meta_key,$ matches)){
$ prefix = $ matches [1]

//收集前缀
$ prefixes [] = $ prefix;

//注意整个行供以后使用
$ user_roles [$ result-> user_id] [$ prefix] = $ result;
}
}

//确保我们只有一个
$ prefixes = array_unique($ prefixes);

//循环遍历我们发现的用户
foreach($ user_roles as $ user_id => $ existing_prefixes){
if(!isset($ existing_prefixes [$ wpdb-> ; prefix])){
//用户可能刚刚被删除 - 所有的行被
// wordpress删除了,所以没有清理我们:)
} else {
//我们希望所有的前缀服从我们(我们刚刚创建或更改
//用户,所以我们想要影响所有网站)
$ desired_role = $ existing_prefixes [$ wpdb-> prefix] - > meta_value;

//循环遍历所有前缀
foreach($ prefixes作为$ prefix){
//要插入/更新的数据
$ cap_data = array $ b'user_id'=> $ user_id,
'meta_key'=> $ prefix。'capabilities',
'meta_value'=> $ desired_role
);

//如果此用户的前缀不存在
if(!in_array($ prefix,array_keys($ existing_prefixes))){
//实际插入用户可能只是创建了)
$ wpdb-> insert($ wpdb-> usermeta,$ cap_data,array('%d','%s','%s'))
} else if($ desired_role!== $ existing_prefixes [$ prefix] - > meta_value){
//更新它,如果不是正确的(用户可能只是编辑)
$ cap_data ['umeta_id'] = $ existing_prefixes [$ prefix] - > umeta_id;
$ wpdb-> replace($ wpdb-> usermeta,$ cap_data,array('%d','%s','%s','%d'))
}
}
}
}
}
}


I have 2 WordPress sites in 2 different sub-domains like test1.abc.com and test2.abc.com . Both sites have wp-require plugin activated and only logged-in users can see the site. We want to make a system where if a user logged into one site, he should be auto-login into the other one.

What i try :

After some searching I know I need to use one database for both sites. So I have done these steps:

I have download the whole database of test2.abc.com site and change all prefix wp_ to wpmo_, replaced it in whole database and upload it into first site's database. I added these 2 lines in wp-config.php of the second site, to define that second site should use first site's user table not its own.

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

Now, the second site is using the first site's users and I am able to login to the second site by the user details of first site.

The next problem is cookies, so I added these lines in wp-config of both sites.

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

Now I logged in into test1.abc.com and when I go to test2.abc.com , it asks me to login. That means cookies are not passing from the first site to the second one. However, i tried to be print $_COOKIE and it gives me same encrypt values, but user still not auto login on second site. also when i came back to first site , it automatic logout. i feel like both sites are related somehow on cookies and i am close but still not reached to my goal of auto login into second site.

Any help?

Solution :

After some help from Mikk3lRo and others, i have managed to solve this issue. i am posting the solution for anyone who faces the same problem. here you can find step by step guide for this :

step 1: use one database for both installations, install 2 wp by using 2 different prefix on installation time.

step 2: Make sure that the randomly generated secret keys and salts are also identical in both wp-config.php files.

step 3: paste these 2 lines in wp-config.php of second site.

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

step 4: share cookies with these lines . (write in both wp-config.php)

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

step 5: now you will be able to auto login in second site when logged into first site. but your will an error message on second site "you do not have permission to access this page", which is a good thing.

step 6: The reason is, WordPress checks the user capability (wp-includes/capabilities.php) so either you have directly add this capability in database (in case you only have few users) or to write a plugin for this. @Mikk3lRo writes a plugin for this in comments, which is Good.

Thanks

解决方案

Alright - you are very close, but there are a few more things to be done.

All requirements are as follows:

  • Share the same database, using different prefixes - you've done this. From here I assume the prefixes are wp1_, wp2_ and so on.
  • Share the wp1_users and wp1_usermeta tables - you've done this - and actually you would have overcome this obstacle if only you had spelled the constants name correctly... it's CUSTOM_USER_META_TABLE (one more underscore than what you have)
  • Share cookies between the subdomains using a common COOKIE_DOMAIN and COOKIEHASH - you've done this
  • Make sure that the (normally) randomly generated secret keys and salts are also identical - you don't write that you've done this, but judging by your results I think either you have or your keys are empty (which is not good, but will work)
  • Make sure there's a prefix_capabilities entry for each user for each site in the shared usermeta table - I don't think you've done this, simply because you haven't yet reached the point where you realize it's necessary.

Complete solution:

This goes in 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');

This is enough to get you logged in on both sites - but there's still that last annoying bullet left on the list.

The problem is that your permissions ("capabilities") are only good on one of the sites because the meta_key is prefixed with the table prefix of the site. If you google around a bit you will find lots of solutions recommending to modify wp-includes/capabilities.php to just use a common prefix instead - I strongly recommend against that! (not for security reasons, but because you will need to make this patch / hack after every update... and it's just insanely bad practice to modify core files)

Instead to remedy this obstacle you need to duplicate the wp1_capabilities row in the wp1_usermeta table (for each user!), giving it a new umeta_id and substituting the table prefix wp1_ with wp2_ in the meta_key column. You need to do this for each site, so you have one row with meta_key wp1_capabilities, one with wp2_capabilities and so on.

If you and a friend of yours are the only users who'll ever log in to the sites, then just do it by hand through phpMyAdmin or something - if you need it to work dynamically, then it should be quite possible to automate with a small plugin (see edit below).

I've always hated this design - a table prefix has no business inside a table row! I think it is needed for multisite installs, though I'm sure there would be other (better) ways to solve it...

Update: Plugin to keep user roles synchronized between all sites

This simple plugin will duplicate and keep the required rows in the usermeta table updated when users are created or edited.

One thing worth noting is that it probably won't work with multisite installs because they have some special capabilities / roles. I have not tested this.

It may need refinement for specific use cases (please do comment), but it does the job fine for my limited test case that only includes a few users. It will be inefficient for a site with thousands of users, but as it only runs when a user is modified, and only does updates if they are needed I doubt this will be a major concern. However it should be relatively easy to adapt to only read and modify the user that was just added / edited. It would complicate initial setup a bit though, as pre-existing users would not automatically get duplicated on the first run.

Create the folder wp-content/plugins/duplicate-caps and inside put the following in duplicate-caps.php - and don't forget to activate under plugins in wordpress admin. It needs to be installed on all sites.

<?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'));
                    }
                }
            }
        }
    }
}

这篇关于共享用户在同一服务器上的2个子域中的2个WordPress安装的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆