Devise の reset_password_token カラムを見て、MySQL のユニークキーが NULL 重複を許可するのを思い出した

Rails4 にて Devise でユーザー登録・ログイン認証・認可の機能を追加 で最初の Devise 用のマイグレーションで、create_table を行いました。

さらに、Rails4 で Devise と OmniAuth で、Twitter/Facebook のOAuth認証と通常フォームでの認証を併用して実装 で、OmniAuth 用のカラムを追加するマイグレーションを行い、OAuth 認証機能を追加しました。

その後、MySQL の中身を眺めたりしてたら思い出したのが表題の件。

スポンサーリンク

MySQL DBのテーブル構造とそのマイグレーションを確認

データベースのテーブル構造は以下の様な状態。

reset_password_token は Null を許可し(Yes)、かつ Key がユニークキー(UNI)と指定されています。

最初の create_table のマイグレーションは以下の通りだったので妥当です。(デフォルトのままでコメントアウト部分は削除。)

reset_password_token には :null => false のオプションが付いていない。そして add_index で :unique => true のオプションが付いている。

User のレコードを何件か追加して、reset_password_token を確認したら NULL が重複してる!

ローカル環境で、試しにTwitter/FacebookでのOAuth認証や、通常のフォームからユーザー登録を行ってみると、テーブルのレコードは以下のようになりました。reset_password_token は全部 NULL になってますね、ユニークなはずなのにあれ?!

reset_password_token というカラム名から推測すると、パスワードリセットの際に使われるトークンなのでしょう。パスワードリセットのリクエストがあったら、該当ユーザーにEメールを送信し、パスワードリセット用のURLをクリックしてもらって、レコードに保存されたトークンと照らし合わせて、トークンが同じだったらパスワード再設定画面を表示してパスワードを変更できる…的な。試してないので予想ですけど。

最初これに気付いた時、なぜ reset_password_token カラムはユニークキー制約してるのに、NULL が重複できるの!?ってなったのですが、その後 MySQL がそういう仕様だったのを思い出しました。そして、これトークンで NULL を指定すれば、他のユーザーのパスワードをリセットできるんじゃないのか?とか不安になったのですが、NULL のトークンを受け付けないなど、きっとしっかり作ってあるはずですよね。このあたりの Devise の動作も、今度確認しないといけない。

スポンサーリンク
パーフェクト Ruby on Rails は、最近読んだ Rails 本の中では一番役に立った本です。Chef や Capistrano など Rails と共によく使用される技術にも触れてあります。Ruby on Rails 4 アプリケーションプログラミングは、入門的な内容で Rails の機能全体を網羅されています。
スポンサーリンク
 
Twitterを使っていますのでフォローお願いたします!ブログの更新情報もつぶやいてます^^
(英語学習用)

Leave Your Message!