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

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

ただいまの
回答率

90.32%

  • Ruby on Rails

    7693questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • CakePHP

    2392questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

  • Facebook

    416questions

    Facebookは、実名登録制のSNS(ソーシャル・ネットワーキング・サービス)です。開発者用のデベロッパーサイトが存在し、一般ユーザーによるFacebook向けアプリケーション開発が可能です。

  • OAuth

    113questions

    OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。

CakePHPからRailsへ焼き直す際に、ユーザー認証がうまく移行できない

解決済

回答 3

投稿

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

ooo

score 18

今回、既存のWebサービスをCakePHP2.xからRails4.xへ焼き直そうとしています。

その際、登録済みのユーザー様については、同じe-mailとパスワードでログインして頂きたく、
Usersテーブルのデータをそのまま移行できないかと考えているのですが、
CakePHPで暗号化したパスワードを、どのようにRailsで突合すればよいのかわからず困っています。

このような場合の移行方法をご教授頂ければ幸いです。


いま、Railsのログイン処理にはdeviseを利用する予定で、CakePHPでは以下のようにパスワードをハッシュしています。

   public function hash($password) {
        return password_hash($password, PASSWORD_DEFAULT);
    }

    public function check($password, $hashedPassword) {
        return password_verify($password, $hashedPassword);
    }

http://qiita.com/hmuronaka/items/73fb9f2986a46905ff3d

ちなみに、こちらのURLの情報を参考に作業してみたのですが、うまくいきませんでした。
そもそもSaltについての理解ができていないのですが、少し調べてみたところ、
私のソースの場合はランダムでSaltを生成するため、
上記URLのようにSaltを固定する場合の解決方法は当てはまらないのではないかと思っております。

※見当違いの解釈をしている可能性がありますが、下記URLの引用部分を読んでそう考えています。

http://php.net/manual/ja/function.password-hash.php
省略した場合は、パスワードをハッシュするたびに password_hash() がランダムなソルトを自動生成します。これは意図したとおりの操作モードです。




【Facebookについて】
なお、CakePHPで作ったサービスにおいてはFacebookログインも利用しており、
RailsではOmniauth-Facebookで、対応するつもりなのですが、
Facebook_uidも既存のものを引き継げないでしょうか。

こちらについては恐縮なのですが、現状本番への影響が怖く、
本番に利用しているFacebookAPP_IDとSecretでは未テストです。
APPとSecretが一致すれば、Facebook側から発行されるuidも一致するのでしょうか?

どうぞよろしくお願いいたします。
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

+3

Saltについての理解

ハッシュ関数は逆計算が困難ではあるのですが、たとえば「apple」のようなありがちなパスワードを使っていた場合にmd5ハッシュをとると 30c6677b833454ad2df762d3c98d2409 になります。 これでGoogle検索すると簡単に元の文字列appleが判明してしまいます。これはmd5に限らず大抵の汎用的なハッシュ関数に言えることで、saltを使わない場合の問題点です。
saltは後ろにサービス固有の文字列を追加することで、その逆計算を困難にする仕組みです。saltが十分に複雑な文字列だった場合、上のような簡単な方法でハッシュの逆計算は出来なくなります。
仮にハッシュ後の文字列が漏洩してもサービスにはログイン出来ないように、ということでこういったsaltを追加します。

大事なのは、設定する時も照合するときも同じsaltを使いっているのだ、と言う事です。そうしないとそもそもhash後の文字列が一緒にならない、認証出来ない、ということになってしまうわけです。
ですから、ランダムだから当てはまらないというのはおかしいです。 あなたのCakePHPのソースコードには、以前にランダムで生成した文字列が、ソースコードに固定で書かれているんじゃないですか?
さて、そういうわけで、昔ランダム生成した文字列をRails側にコピペして持ってきてしまいましょう。その上で先のQiitaの記事の通りにすれば上手く行くはずです。

Facebookの方ですが、理屈の上ではそうですが、テストしないと結構、危なそうですね。
DBの内容を引っ張ってきて、ローカル環境やステージング環境できっちりテストするのが良いと思いますよ。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/04/16 20:06

    ご回答いただきましてありがとうございます!

    >>設定する時も照合するときも同じsaltを使いっているのだ、と言う事です。そうしないとそもそもhash後の文字列が一緒にならない、認証出来ない、ということになってしまうわけです

    ここについて、AknEpさんのおっしゃる通りだと思っていたため、
    自分のSaltの理解について納得がいっておりませんでした。
    というのも、「ハッシュのたびにSaltをランダムで生成するなら、照合するときどうやってるんだろう•••」と、質問文中で引用しているPHPマニュアルの以下の部分を読んで混乱しておりました。

    "省略した場合は、パスワードをハッシュするたびに password_hash() がランダムなソルトを自動生成します。これは意図したとおりの操作モードです"


    >> あなたのCakePHPのソースコードには、以前にランダムで生成した文字列が、ソースコードに固定で書かれているんじゃないですか?

    これはまさにそうです!
    やはり固定Saltを利用するということで間違いないようで、
    前回照合に失敗していたのは私の手順にミスがあったんでしょうね。
    これで安心して試行錯誤できます!ありがとうございます!

    Facebookについては本番デプロイ前に、
    必ずステージング環境でテストするようにしますね。

    とても困っていたので、素早いご回答を頂けて助かりました!
    本当にありがとうございました!

    キャンセル

  • 2015/04/16 21:49

    【追記】
    Lohn様のご回答が解決に直結していたため、
    大変恐縮ですがベストアンサーを振り替えさせていただきました。

    重ね重ね、ご回答頂きましてありがとうございました!

    キャンセル

  • 2015/04/16 21:51

    Lohnさんの回答が気になって調べてみたところ、勘違いがあったのが解りました。少し補足します。

    結局CakePHPでもRailsでもsaltは固定値なようで、ちょっと余談ではあるのですが。
    PHPの password_hash() ではランダムなsaltを使ってハッシュ化を行い、その返り値は"ハッシュ値<ドット>ハッシュ化に使ったランダムなハッシュ値" という文字列を返し、password_verifyはその文字列を受け取るとランダムハッシュ値を利用して有効かどうかの確認をしてくれるみたいです。

    何にせよ、処理系が違うこともあり、ちょっとしたオプションの違いでマッチしなくなる事が予想されますね。(しかもCakeもRailsのDeviseも内部のブラックボックスに押し込まれてるから追いかけるのがちょっと大変です)慎重にがんばってくださいね。

    キャンセル

  • 2015/04/16 22:16

    >>PHPの password_hash() ではランダムなsaltを使ってハッシュ化を行い、その返り値は"ハッシュ値<ドット>ハッシュ化に使ったランダムなハッシュ値" という文字列を返し、password_verifyはその文字列を受け取るとランダムハッシュ値を利用して有効かどうかの確認をしてくれるみたいです。

    ご丁寧にありがとうございます!
    なるほど!!php側のverifyメソッドでハッシュ値の有効性を確認してるんですね。
    ということはブラックボックスに手を突っ込まない限り、
    rails側のauthenticate_phpが完全にphp5互換していることを信じて進むしかないんですね•••笑
    既存データに関してはバッチでもまわして全件テストしてみようと思います!

    ありがとうございました!

    キャンセル

checkベストアンサー

+2

Saltについて
まずは、ご自身が利用されている暗号化方式について確認されるのが良いと思います。
※現行のCakePHPでは、BCrypt(Blowfish)を利用しているのだと思いますが、qiitaのリンク先を見たところSHA/MD5を使用していますね。

BCryptのソルトとSHA等のソルトはそもそも概念が違うので、混乱する元になっていると思います。
(BCryptにはSHA等のソルトと同様の、ペッパーという概念はありますが)

BCryptについては、下記のページが参考になると思います。
http://www.kamiya54.info/post/100503173956/bcrypt-blowfish
http://php.net/manual/ja/faq.passwords.php

Deviseでは、デフォルトでBCryptを使用するようになっています。
パスワードが一致するかを試す場合は、以下のような方法で簡単に確認することができます。
BCrypt::Password.new( "CakePHPで暗号化済みのパスワード" ) == "password"

なおDeviseで使用するためには encrypted_password カラムに暗号化されたパスワードを保存する必要があります。

Facebookについて
こちらは割愛します。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/04/16 21:46

    ご回答いただきましてありがとうございます!

    はい、既存データの形式を見る限りBCrypt(Blowfish)を利用しておりました。
    Bcryptのソルトはまた別物なのですね•••参考に貼って頂いたリンクで完全に理解できました。

    本問題の解決に直結していたので、恐縮ながらベストアンサーとさせて頂きました。
    クリティカルなご回答に頭が上がりません。

    大変助かりました、本当にありがとうございます!

    キャンセル

0

結論としては、cakephpで作成されていたBCryptパスワードは$2yアルゴリズムで作られていましたが、
Rails側のBCyrptのデフォルト認証アルゴリズムは$2aだったことが原因でした。
解決方法は、Cakeで作成されたパスワードの$2y部分を、$2aに直接書き換えるだけです。
これで認証されるようになるのも驚きましたが、大丈夫なようです。
なので、以下SQLを流して完了でした。
UPDATE users SET encrypted_password=REPLACE (encrypted_password,"$2y$10","$2a$10");

例)
Cakeで作成されたパスワード
$2y$10$amONVVOTZP3rqIzbYnVHyuzbIFZ/fzPY/il4qPMNBbJlUoQyGVTm2
RailsのBCrypt::password.newで認証成功するパスワード
$2a$10$amONVVOTZP3rqIzbYnVHyuzbIFZ/fzPY/il4qPMNBbJlUoQyGVTm2

お二人に頂いた情報をもとに試行錯誤していた結果、以下のページに辿りついたので、
参考までにURLを貼っておきます。ありがとうございました。

http://stackoverflow.com/questions/20980859/using-bcrypt-ruby-to-validate-hashed-passwords-using-version-2y

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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

  • Ruby on Rails

    7693questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

  • CakePHP

    2392questions

    CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

  • Facebook

    416questions

    Facebookは、実名登録制のSNS(ソーシャル・ネットワーキング・サービス)です。開発者用のデベロッパーサイトが存在し、一般ユーザーによるFacebook向けアプリケーション開発が可能です。

  • OAuth

    113questions

    OAuth(Open Authorization)は、APIを通して保護されたリソース(サードパーティのアプリケーション)へアクセスする為のオープンプロトコルです。