遷移を自然に行いたい
会員制のWPサイトを作ったはいいがポコポコ作りすぎたので、
こっちでログインさせたらそれを引き継いで派生WPサイトでもログインを継続させたいじゃない。
前提。WPのユーザー情報を共有させたWPサイトであること
https://mirai-creators.com/3755/
「wp-user 共有」あたりで検索すると引っかかるので、このやり方でWPをインストールして作成したサイトであること。
DB自体を共有するやり方。
最低限、user-idが同じであれば以下で述べる内容は使えるかもしれない。
影響するファイル。
本サイト(ログイン情報を持ってるサイト)
function.phpとjavascriptファイル。
あとはaタグ系にクラス付け。
派生サイト(自動ログインさせたいサイト)
function.phpとheader.php辺り。
懸念点
なるべくブラウザから通常のやり方でハックされないやり方にしたいのでPOSTを使った。
ただ、プログラムからブルートフォース的にアタックされると危ないので暗号化を噛ます。
渡すパラメータを暗号化して、コマンド命令も暗号化すればしばらくは持ちこたえるのではないか。
紹介したのは最低限として、ここから先は腕の見せどころで。。
やり方
本サイト(ログイン情報を持ってるサイト)
基本的な流れは以下。
- クラス付けしたaタグの情報をjavascriptで受ける。
- javascriptからwpのajax機能を使って情報を組み立て、javascriptに返す。
- javascriptでajaxで受け取った情報をpostする。
wpでのajaxの使い方はこの辺のサイトで。簡単。
https://engineering.dn-voice.info/blogwordpress/ajax/
<a class="my01_ajax" href="/bbb/" target="_blank">to bbb site</a>
// ajaxリクエストURL
add_action('wp_head','add_my01_ajaxurl',1);
function add_my01_ajaxurl() {
?>
<script>
var my01_ajaxurl = '<?php echo admin_url( 'admin-ajax.php'); ?>';
</script>
<?php
}
add_action('wp_ajax_my01_ajaxpost','func_my01_ajaxsubmit');
add_action('wp_ajax_nopriv_my01_ajaxpost','func_my01_ajaxsubmit');
function func_my01_ajaxsubmit(){
$ret_ary = array();
if (is_user_logged_in()) {
$ret_ary = array();
if (isset($_POST['command'])) {
$user = wp_get_current_user();
$user_id = $user->ID;
$cmd = $_POST['command'];
$my01_uid = $user_id;
$my01_phrase = "aaaaiiiiuuuueeeeooooooo123456";
$ret_ary["userid"] = openssl_encrypt($my01_uid,'AES-256-CBC',$my01_phrase);
$ret_ary["action"] = $_POST['href'];
if ($_POST['target']) $ret_ary["target"] = $_POST['target']; // _blankとか反映
$ret_ary["method"] = "POST";
if ($cmd == 'logout_js_hirabun') {
$ret_ary["command"] = openssl_encrypt("mylogout123456toOtherWP",'AES-256-CBC',$my01_phrase);
}
if ($cmd == 'login_js_hirabun') {
$ret_ary["command"] = openssl_encrypt("mylogin123456toOtherWP",'AES-256-CBC',$my01_phrase);
}
}
$ret_ary["result_status"] = "success";
} else {
$ret_ary["result_status"] = "no login";
$ret_ary["action"] = $_POST['href'];
if ($_POST['target']) $ret_ary["target"] = $_POST['target'];
}
$result = json_encode($ret_ary);
header("Content-type: application/json; charset=UTF-8");
echo $result;
die();
}
ログイン時以外は
パスフレーズは受け側サイトと合わせて適当に。
暗号化方式も色々あるみたいなので適当に受け側サイトとそろえる。
https://qiita.com/zaburo/items/e2f08d40d8f8d9ae875f
コマンド名も独自のものを受け側サイトとそろえる。
// ajax function
$(function(){
var func_afterdo = function (own, data1, textStatus, jqXHR) {
// alert(textStatus+":"+JSON.stringify(data1));
if (data1.result_status!="success") {
if (data1.target) {
open(data1.action,data1.target);
} else {
window.location.href = data1.action;
}
return false;
}
$('<form/>',{action:data1.action, method:data1.method, target:data1.target})
.append($('<input/>', {type:'hidden',name:'my01cmd',value:data1.command}))
.append($('<input/>', {type:'hidden',name:'my01data',value:data1.userid}))
.appendTo(document.body)
.submit();
return false;
};
var funcAjax = function (my01_ajaxurl, cmd, href, target) {
var fd = new FormData();
fd.append('command', cmd);
fd.append('href', href);
if (typeof target !== "undefined") {
fd.append('target', target);
}
fd.append('action','my01_ajaxpost');
return $.ajax({
type: 'POST',
url: my01_ajaxurl,
data: fd,
processData: false,
contentType: false,
timespan: 1000,
});
};
// aタグ受け
$('a.my01_ajax').click(function(){
var own = $(this);
var href = own.attr("href");
var target = own.attr("target");
// ajaxの通信 ログインコマンドが平文
funcAjax(my01_ajaxurl,"login_js_hirabun",href,target).done(function(data1, textStatus, jqXHR) {
func_afterdo(own, data1, textStatus, jqXHR);
}).fail(function(jqXHR, textStatus, errorThrown) {
// own.parent().find('.resultarea').html(textStatus+":"+errorThrown+" > "+JSON.stringify(jqXHR));
});
return false;
});
});
jsは平文で読めてしまうので、変数名は難読化したほうが安全かも。
ていうかファイル自体をminifyしたらいいか。
派生サイト(自動ログインさせたいサイト)
基本的な流れは以下。
- テーマファイルの一番先頭で呼び出されるであろうファイルの先頭に関数呼び出しを仕込む。通常はheader.php。
- function.php内の関数で、POSTされていたら判定して自動ログイン
<?php my_after_my01my01(); // header吐き出し前、ファイル先頭で呼び出すこと ?>
<!DOCTYPE html>
function my_after_my01my01(){
if (is_user_logged_in()) return;
if (isset($_POST['my01data']) && $_POST['my01data']) {
$cmd = $_POST['my01cmd'];
$my01_uid = $_POST['my01data'];
$my01_phrase = "aaaaiiiiuuuueeeeooooooo123456";
$my01_uid = openssl_decrypt($my01_uid,'AES-256-CBC',$my01_phrase);
$cmd = openssl_decrypt($cmd,'AES-256-CBC',$my01_phrase);
if ($cmd == 'mylogin123456toOtherWP') {
if (is_numeric($my01_uid)) {
$udata = get_user_by('id',$my01_uid);
if (udata->ID) {
wp_clear_auth_cookie();
wp_set_current_user($udata->ID);
wp_set_auth_cookie($udata->ID, true);
}
}
}
if ($cmd == 'mylogout123456toOtherWP') {
wp_clear_auth_cookie();
}
}
return;
}
受け側は単純、useridとコマンド文が正しく復号化できていたら自動ログインさせるだけ。
ログアウトのやつは未検証でおまけ。
同時ログアウトは、たぶん難しい。
2サイトまでなら同期できそうだけど3サイト以上だとどうやるんだ・・ってなる。
メンテナンスが大変になるやり方は嫌だな・・