Railsでパスワードのハッシュ化にPHPのcrypt関数的なことを行う
よくPHPでパスワードの文字列をハッシュ化してデータベースへ保存したり読み込んだりするために、crypt関数を使ったりしていた。
だが、Ruby on RailsだとmodelでDBのカラムを持たせずにパスワードを出し入れする方法はあれど、PHPのcryptに相当するようなメソッドが見当たらないみたいだった。
連番とかをつけたりするような順次処理とかはmodelを使って定義したほうがいいかもしれないけど、この手の保存と読込ってコントローラー側の方で制御できたほうが何かと便利なんだよね。
なので、そこまで高度なコードでもないのでRailsのコントローラーの共通メソッド置き場であるapplication_controller.rbに以下のコードを追加して対応することにした。
class ApplicationController < ActionController::Base ~~~ SALT = 'SALT' ~~~ def crypt(string = 'string', salt = SALT) return Digest::SHA1.hexdigest("#{salt}#{string}") # return Digest::MD5.hexdigest("#{salt}#{string}") end ~~~ end
SHA1とMD5は好きな方でいいと思う。
Railsだとrequire ‘digest/sha1’とかrequire ‘digest/md5’とかモジュールを読み込まなくても動くのね。Ruby単体だと動かなかった記憶あるけど。(うろ覚え)
saltの引数の初期値はとりあえず定数SALTにしておいた。データベースの作成日とかをテーブルに記録しておいて、それにすげ替えてもいいのかもしれない。
コントローラー側ではこのように使用する。
class UsersController < ApplicationController ~~~ def methodname # 書込例 User.where(:user_id => session[:user]).update_all( :password => self::crypt(password, '【ソルトの文字列】') ) # 比較例 user_data = User.find_by(:user_id => 'cattlemute') password = self::crypt(【POSTとかで飛ばしてきたパスワード文字列】, '【ソルトの文字列】') if password === user_data.password 【一致のとき】 else 【不一致のとき】 end end ~~~ end
定数で代替文字列入れてるからsaltの指定は任意。
つーかいちいち指定するのめんどうくせぇな。しょうがないけど。
PHPのcryptだと関数がsaltを自動生成してくれるので、同じようにしたいところだけど、リアルタイムの日付とかにしちゃうと値をDBへ保存したのと比較するときに不都合が出るんだよなぁ。
まぁ、本家でもsaltの入力は推奨されてるからとりあえずはいいか。
あとは、本家のcryptと同じだけど、飽くまでハッシュ化なので復号化はできないので注意。(そもそもハッシュ化と復号化は対義語ではないけど)