パスワードとかを暗号化する際にBCryptを良さげなので Rails+MongoDBでの導入方法から使用方法まで
やりたいこと
Rails+MongoDBでパスワードフィールド(RDBでいう属性、カラム)とか 生で保存したくないデータを暗号化したいとき
BCryptとは
認証で使用するパスワードを安全にハッシュ化するアルゴリズム。 SHA256等では暗号化として不足するため(下記参照)、 saltと呼ばれる短いランダムな文字列を末尾に加えて暗号化する。 レインボーテーブル(ハッシュ値に対して総当たりで平文を得ようとする)に対して強力のようです
よくあるHash関数アルゴリズムは(元々高速に計算することを意図していたのもあり)非常に高速に計算が可能であり、総当たり試行されてしまえば、現代のコンピュータスペックをもってすれば一瞬で解読されてしまいます。また、レインボーテーブルと呼ばれる、高速にHashから元の値を類推することが可能なアルゴリズムも存在し、Hash化では不足です。
インストール
Gemfileに下記を追加し、bundle install
でインストールできます
# パスワード暗号化Gem gem 'bcrypt', '~> 3.1.11'
model
app/models内の暗号化したいフィールド(属性、カラム)があるモデルについて
下記の様にhas_secure_password
メソッドを使用します。
class Hoge # has_secure_passwordが存在しない。というエラーが発生したら追加します include ActiveModel::SecurePassword # パスワード暗号化 has_secure_password end
Hogeモデルにpassword_confirmationフィールドが追加され、 validateも自動で追加されます。 authenticateメソッドが使えるようになります
なおRDBの場合、password_digest属性の追加されたことにより マイグレーションが必要になります。 (MongoDB等のNoSQLの場合不要です)
ViewおよびControllersでの使用方法
View側でpasswordをform_tagで送り、Controllersでドキュメント(行、レコード)を追加することで こうすることでbcryptがpassword_digestフィールドに暗号化されたパスワードを入れます。 Controllers側では暗号化に関わる処理は特に何もする必要はないです。
以下ユーザ登録フォームでの使用方法例
例
app/views/userCreate.erb
<h4 class="">ユーザー登録</h4> <%= form_tag("/user/create") do%> <p class ="">名前</p> <input class="" name = "name"> <p class ="">Eメール</p> <input class="" name = "email"> <p class ="">パスワード</p> <input type="password" class="" name ="password"> <div class=""> <input type="submit" class="btn btn-primary" value="登録"> </div> <% end %>
/config/route.rb
post "/user/create" => "user#userCreate"
app/controllers/user_controller.rb
def userSignUp @user = User.new end
パスワード認証方法
先ほどは暗号化したパスワードを格納しましたが、 今度はパスワードを画面入力した際など、画面から生のパスワードデータがきたときのControllers側の処理はauthenticateメソッドを利用します。
以下、ログイン画面を想定した使用例です
/app/views/login.erb
<%= form_tag("/user/login") do%> <p class="">ユーザ名</p> <input class="w-150" name="name"> <p class="">パスワード</p> <input type="password" class="" name="password"> <div class=""> <input type="submit" class="btn btn-primary" value="ログイン"> </div>
/config/route.rb
post "/user/login" => "user#userLogin"
app/controllers/user_controller.rb
def userLogin @user = Hoge.find_by(name: params[:name]) # @user.authenticateで入力されたパスワードを暗号化した後に # password_digestフィールドと比較 if @user && @user.authenticate(params[:password]) flash[:notice] = "ログインしました" redirect_to("/Fuga") else @errorMessage = "ログインに失敗" render("/login") end end
参照
Railsにおけるパスワードの扱い方(BCrypt)
BCryptのすすめ
どちらもありがとうございます。