質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.64%

2つのWordpressサイトを同時にログインできるAPIを作成

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,836

omusoba

score 27

こんにちは。
現在ローカルで試しているのですが、2つのwordpressのログインをそれぞれのサイトで行うのが面倒なので、片方でログインしたら双方ログイン状態にできないかと思い試験的に作成しています。

【前提】
1、ユーザー管理はプラグイン[wp-members]を使用。
2、プラグイン[wp-members]内の[wp-members-core.php]のlogin()ファンクション内でサインオンの処理が完了した後にAPIでもう片方のサイトにもログイン処理をしておく。
3、ユーザー情報自体は別々のデータベースで管理しているが、まったく同じユーザー情報が入っている(後々同期処理を行う処理を追加予定)
4、ローカルでは現在MANPを使用中

【ファイル構成】
MAMP/htdocs

wordpress1   (localhost:8888/wordpress1)
→wordpressapi
「synchro_login.php」
→wp-admin
→wp-content
→wp-includes    .etc.....

wordpress2   (localhost:8888/wordpress2)
→wordpressapi
「synchro_login.php」
→wp-admin
→wp-content
→wp-includes    .etc.....

【ログイン処理側】

/* localhost:8888/wordpress1/wp-content/plugin/wp-members/wp-members-core.php内 */

$user = wp_signon( $creds, false );
    if( ! is_wp_error( $user ) ) {
           //サイト間ログイン同期処理追加
                    $another_site = get_option('st_link_url');//localhost:8888/wordpress2/
                    $url = $another_site."wordpressapi/synchro_login.php";
                    $data = array('access_token' => $user_token,'userid' => $user->ID,'password' => $user_pass);

                    $header = array("Content-Type: application/x-www-form-urlencoded","Content-Length: ".strlen($data));
                    $context = array(
                        "http" => array(
                            "method"  => "POST",
                            "header"  => implode("\r\n", $header),
                            "content" => $data
                        )
                    );
                    $contents = file_get_contents($url, false, stream_context_create($context));
                    if($contents !== false){
                        $result = json_decode($contents, false);
                        if (!$result->rcode) {
                            $redirect_to = apply_filters( 'wpmem_login_redirect', $redirect_to, $user->ID );
                            wp_redirect( $redirect_to );
                        }else{
                            return "loginfailed";
                        }
                    }else{
                        return "loginfailed";
                    }           
                    //サイト間ログイン同期処理追加
  } else {
      return "loginfailed";
}

【API側】

/* localhost:8888/wordpress1/wp-content/plugin/wp-members/wp-members-core.php内 */

header("Access-Control-Allow-Origin: *");
require_once('../wp-load.php');

global $wpdb;
$result = new stdClass;
$result->rcode = 0;
$result->errorcode = 0;

// パラメータ存在チェック
if (!isset($_POST['userid']) || empty($_POST['userid'])) {
    $result->rcode     = -1;
    $result->errorcode = 1;
}

if (!isset($_POST['password']) || empty($_POST['password'])) {
    $result->rcode     = -1;
    $result->errorcode = 1;
}

if (!isset($_POST['access_token']) || empty($_POST['access_token'])) {
    $result->rcode     = -1;
    $result->errorcode = 1;
}

//アカウント存在チェック分岐
if (!$result->rcode) {

    $post_ID = $_POST["userid"];
    $post_pass = $_POST["password"];
    $post_token = $_POST["access_token"];
    $rememberme = ( isset( $_POST['rememberme'] ) == 'forever' ) ? true : false;

    $creds = array();
    $creds['user_login'] = $post_ID;
    $creds['user_password'] = $post_pass;
    $creds['remember']      = $rememberme;

    $user = wp_signon( $creds, false );

    if( ! is_wp_error( $user ) ) {

        if($contents !== false){

            wp_set_auth_cookie( $user->ID, $rememberme );

         }else{

                $result->rcode     = -1;
                $result->errorcode = 3;

            }

        }else{

            $result->rcode     = -1;
            $result->errorcode = 4;

        }

    } else {

        $result->rcode     = -1;
        $result->errorcode = 5;

    }

}
$result_JSON = json_encode($result);
echo $result_JSON;

サインオン自体の処理はできており、その後に発行しているアクセストークンやユーザー情報の取得もできています。
ただ、どうしてもその後に行うもう一つのサイトに向けてPOST送信を行うとfalseで返ってきます。
この場合、API側の方で受け取れておらず送信の際に何か起きている(送信の仕方が悪い)と考えています。
送信方法などでcurlの送信方法で試してみた所、同じくnullでした。
試しに直接API側にブラウザでアクセスすると{"rcode":-1,"errorcode":2}と、動くことはうごいています。

こういった方面に知識がおありの方がいらっしゃいましたらご助力いただけば幸いです。

【追記】
googleのツール「Advanced REST client」でPOST送信の返り値などを確かめるためにデバッグで確かめていたらもう一つわかりました。
API側の受け取り時、POSTの変数が空になっておりました。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+1

頑張って自作しなくても、
シングル・サインオンのプラグインを活用したほうがスマートに実装できそうな気がします。

参考:single sign-on — タグ — WordPress Plugins
https://ja.wordpress.org/plugins/tags/single-sign-on

例えば、WP OAuth Server — WordPress Plugins
https://ja.wordpress.org/plugins/oauth2-provider/
を使えば、WordPressのサーバーがOAuthのサーバーになれるわけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/11/04 12:21

    ご回答ありがとうございます。
    サイトやプラグインについては少し確認してみました。
    ですが、今後ユーザー情報の変更の操作やユーザーの新規作成などの操作に対しても両方のサイトのユーザー情報の同期を取っていく予定でして、しかもこのサインオンの前の処理に一意なアクセストークンを発行しており、それをユーザーのメタ情報にアップデートしています。
    その情報も同期していくので、実際の所DBの上書き自体は問題ないのですが、質問で挙げた様なAPIに近い処理が必要だと思い作成しました。

    今回の大きな問題としては「APIを作成する」ということではなく、 「file_get_contentsの操作がうまくいかない」というのが主題になります。

    キャンセル

  • 2016/11/04 12:33 編集

    file_get_contents()がうまくいかないのは、(1)瞬時に応答を返していな可能性、(2)contextをstream_context_create()で生成したものを一旦変数に格納しないといけない可能性、とかでしょうか。stream_context_create()を使ったサンプルコードが必ず変数保持しているように見えるので。

    キャンセル

  • 2016/11/04 13:34

    一度contextをstream_context_create()で生成したものを変数に入れてから行いましたがやはり結果は変わりませんでした。

    送り先自体は間違ってはいないはずなのですが(直接urlをブラウザから開いて確かめたりしているので)、PHP同士でのやりとりかつローカル同士で行なっているのでそうなるとサーバーのタイムアウトになってfalseで帰ってきてることになるんでしょうかね....。

    キャンセル

check解決した方法

0

$ch=curl_init();
                    curl_setopt($ch,CURLOPT_URL,$url);
                    curl_setopt($ch,CURLOPT_POST, TRUE);
                    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
                    curl_setopt($ch,CURLOPT_HEADER,FALSE);
                    curl_setopt($ch,CURLOPT_RETURNTRANSFER,TRUE);
                    curl_setopt($ch,CURLOPT_FOLLOWLOCATION,TRUE);
                    curl_setopt($ch,CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko');

                    $result = curl_exec($ch);

今思えば同じサーバーで動かす前提なので、わざわざfile_get_contentsを使用する必要がなかったかもしれません。
なのでできなかったcurl処理にユーザーエージェントを偽装して送信したら値を受け取ることができました!
ご回答していただいてありがとうございました!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る