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

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

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

2回答

616閲覧

1つのWEBサービスにログインしているユーザーを別のサービスにもログインさせたい

monjasfv

総合スコア6

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

2クリップ

投稿2017/08/25 02:57

編集2017/08/25 06:01

###実現したいこと
PHPで複数のWEBサービスを運営しています。
実現したいのはサービスAでログインしているユーザーをサービスBにもログインさせることです。
自分なりに方法を考えてみましたが、これは安全でしょうか?
また、別にどのような方法が考えられるでしょうか?
よろしくお願いします。

###前提

  • AとBどちらもID・パスワードでログインする
  • 同一人物がAとB両方に登録している場合、ログインID・パスワードはAとBで共通
  • AとBは別サーバー、別ドメインであるためセッションは共有できない
  • AとBのDBサーバーは同じ(DBは別)
  • Aにログインすると同時にBでログイン状態になる必要はない(AからBにログインするときはリンクをクリックする)

追記

  • ログイン後にA⇔Bで行き来したい(「Aへ」「Bへ」のようなリンクで移動できればOK)
  • AとBのDBは別である必要がある(AでもBでもない別DBから共通のviewは作成できる)

追記ここまで

###自分なりに考えた方法

ログインIDとトークンを使用する方法を考えました。

A→Bにログインする場合

最初にトークンを保存するテーブルを作成します。
テーブル構造

  • id: autoincrement 主キー
  • login_id: varchar
  • content: varchar ランダムな文字列 md5(uniqid(mt_rand(), true))
  • expiration_date: datetime トークンの有効期限(トークン作成から10秒後)
  • is_used: tinyint 未使用=0, 使用済み=1

####Bにtokenを発行するapiを追加
他者にapiを使われないようにurlに?key=abcd1234のような固定のキーを持たせ、一致した場合のみ処理をするようにします。
以下のようなイメージです。

function createTokenAction($request) { $key = $request->get('key'); $loginId = $request->get('login_id'); if ($key !== self::KEY) { throw new \Exception(); } $token = new Token; $token->loginId = $loginId; $token->content = md5(uniqid(mt_rand(), true)); $token->expirationDate = date('Y-m-d H:i:s', strtotime('+10 seconds')) $token->isUsed = 0; $token->save(); return json_encode(array( 'token' => $token->content, )); }

####BにログインIDとtokenを使用したログインを追加
URL: b.com/loginWithToken/?login_id=hoge&token=abcd1234

functin loginWithTokenAction($request) { $loginId = $request->get('login_id'); $tokenContent = $request->get('token'); $token = Token::findBy(array( 'loginId' => $loginId, 'content' => $tokenContent, )); if (!$token) { throw new \NotFoundExpcetion(); } $now = new \DateTime(); if ($now > $token->expirationDate || $token->isUsed) { throw new \Exception(); } $token->isUsed = 1; $token->save(); // ログインさせる Auth::login($loginId); $this->redirectHome(); }

####AにBへのログイン処理を追加
Bのトークン作成apiでトークンを取得し、BのloginWithTokenにリダイレクトします。
URL: a.com/loginToB

function loginToBAction($request) { $key = self::KEY; $loginId = $this->getUser()->loginId; $url = sprintf('https://b.com/createToken/?key=%s&login_id=%s', $key, $loginId); $json = file_get_contents($url); $data = json_decode($json, true); $token = $data['token']; $url = sprintf('https://b.com/loginWithToken/?login_id=%s&token=%s', $loginId, $token); return $this->redirect($url); }

以上のような方法でBへのログインが実現できそうですが、この方法が安全なのか、また、他にもっといい方法が無いか、教えていただきたいです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

CHERRY

2017/08/25 03:03

方法に関しては、キーワードとしては、「シングルサインオン」で検索すれば、いろいろ見つかると思います。
m.ts10806

2017/08/25 05:32

ログイン後にA⇔Bで行き来することはあるかどうかも前提条件に加えた方が良いと思います。また、DBが別ではなく同じなのはダメかどうかも。
guest

回答2

0

そもそも論ですが、双方のサービスで使用する login_id を一意に保つために、認証用のテーブルは共通である必要があると思います。
そうであるならば、特に複雑な機構は考える必要はなく、そのテーブルを使用して認証すれば良いだけかと。

投稿2017/08/25 04:11

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

シングルサインオンとかシングルサインインとか言われているものです。

認証周りは正常系は簡単にできますが異常系を考慮するのが難しく、自作は避けるのが定石です。出来合いのライブラリを使う事を強くお勧めします。

シングルサインオンについてはSoftware DesignかWeb+DB Pressで特集記事があったと思います。バックナンバー探してみてください。


コードも見てみましたが、「ユーザーID」と「キー」さえ取得できればAとは無関係に任意にトークンを発行しBにログインできます。事実上Bの認証を固定パスワードに変更しただけで、シングルサインオンとは言えないです。

投稿2017/08/25 03:24

編集2017/08/25 07:56
suzukis

総合スコア1449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

monjasfv

2017/08/26 14:00

ご回答ありがとうございます。 >事実上Bの認証を固定パスワードに変更しただけ おっしゃる通りですが、URLが公開されていないこと、十分に長いキーを使用することで安全であるとはいえないでしょうか? また、より安全な方法を考えました。 - 別DBにtokenを保存するテーブルを作成 - そのビューをAとB両方のDBに作成 - AからBへログインするとき、Aでtokenを作成して保存、BのログインURLにloginIdとtokenを渡す - BでURLのloginIdとtokenを使用してログイン 以上の方法で何か危険はあるでしょうか?ご回答いただけると嬉しいです。よろしくお願いします。
suzukis

2017/08/26 15:54

自作はやめましょうと言っています。思いつきレベルでは安全なものを作るのは絶対に不可能です。どうしてもやりたいのであればまずはWebセキュリティの基礎から勉強が必要です。
退会済みユーザー

退会済みユーザー

2017/08/27 14:38

suzukisさん、これ、SSOのどの方式なら実現できそうとイメージしています?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問