やりたいこと
PHPで作られたサービスと、Railsで作られたサービスの2つがある。
ユーザーがPHPのサービスにログインしたときに、同時にRailsのサービスにもログインできているようにしたい。
環境
Rails 5.2.0
PHP 5.6.32
解決方法
PHPのサービスとRailsのサービスは同じルートドメイン(サブドメインは違う)で動作させているので、cookieを共有できる。
これを利用してPHPサービスにログインされた際、PHPのプログラムからRailsサービスに対してログインし、返ってきたcookieをユーザーのブラウザにも焼いてあげる。
そうすることでPHPサービスにログインしたものと同じブラウザでRailsサービスにアクセスしたら、ログインできているようになる。
Rails側のコード
session_store.rb に、サービスが動作するルートドメインを書いてあげる。
config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store, key: "session_test", domain: ".clst01.innova-jp.net"
Rails側のログイン画面
deviseで生成されるviewをそのまま使っている。
PHP側のコード
login.php
$params = array(
"user[email]" => 'test@innova-jp.com',
"user[password]" => 'xxxxxx',
"user[remember_me]" => '0',
"commit" => "Log in"
);
$cookie_path = '/var/www/html/login_cookie';
touch($cookie_path);
$url = "https://session-test.clst01.innova-jp.net/users/sign_in";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_path);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_path);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$output = curl_exec($ch) or die('error ' . curl_error($ch));
curl_close($ch);
$cookie_string = file_get_contents($cookie_path);
$cookie_values = explode("\n", $cookie_string)[4];
$cookie_values = explode("\t", $cookie_string);
setrawcookie("session-test", trim($cookie_values[6]), 0, "/", ".clst01.innova-jp.net");
unlink($cookie_path);
焼かれるcookie
意図した通りにcookieが焼けていると、Chromeで確認した時に下記の画像のようになる。
[ドメイン]項目にルートドメインが記載されているのがポイント。
備考
PHPのCURLOPT_COOKIEJAR で保存されるファイルから、cookieの値だけ取り出す方法がわからなかったのでexplode で頑張ってる。
もっとスマートな方法がありそうな気がする、