Railsで、ユーザを作って、ユーザのパスワードを可逆暗号で暗号化してから保存します。
環境
- Ubuntu 14.10
- Ruby 2.1.5
- Rails 4.2
ユーザテーブルの作成
ユーザテーブルのカラムは、ユーザー名の name:string
とパスワードの password:string
です。
rails generate scaffold user name:string password:string
カラムを空で保存したくないので、マイグレーションファイルを少し書き変えます。
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, null: false
t.string :password, null: false
t.timestamps null: false
end
end
end
そして、rake db:migrate
します。
検証の追加
ユーザモデルに検証を追加します。
とりあえず、user カラムと password カラムは空でなく、さらにユニークであるという検証を追加しました。
この時、フォームが空だったら uniqueness の検証はスキップするようにしてます。
class User < ActiveRecord::Base
# userカラムとpasswordカラムは空でなくユニークである
validates :name, :password,
presence: true,
uniqueness: { allow_blank: true }
end
passwordカラムの暗号化
暗号化は、データの保存前におこない
暗号化には、ActiveSupport::MessageEncryptor を利用します。
ちなみに、暗号化には標準添付ライブラリの OpenSSL を使っているので、ライブラリに対応した暗号化方式を CIPHER
で指定したら好きな暗号化方式を選べます。
モデルを変更
class User < ActiveRecord::Base
# userカラムとpasswordカラムは空でなくユニークである
validates :name, :password,
presence: true,
uniqueness: { allow_blank: true }
before_save :encrypt_password
def encrypt_password
self.password = encrypt(self.password)
end
# SECUREは短いとエラーを吐く
SECURE = 'HOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGEHOGE'
CIPHER = 'aes-256-cbc'
# 暗号化
def encrypt(password)
crypt = ActiveSupport::MessageEncryptor.new(SECURE, CIPHER)
crypt.encrypt_and_sign(password)
end
# 復号化
def decrypt(password)
crypt = ActiveSupport::MessageEncryptor.new(SECURE, CIPHER)
crypt.decrypt_and_verify(password)
end
end
暗号化する encrypt
メソッドを定義し、コールバックを使用して、データの保存前に実行するようにしました。
さらに、復号化する decrypt
メソッドも定義しました。
実際に使用するときは、SECURE
や CIPHER
は適切な場所に定数として定義した方がいいです。
これで、パスワードが暗号化されて保存されます。
確認
実際に暗号化されているか確認します。
rails s
でサーバを起動したら、http://localhost:3000/users/new
にアクセスします。
そしてフォームに値を入力してサブミットしたら、コマンド rails dbconsole
を実行して select * from users;
を実行すると、暗号化の確認をすることができます。
終わりに
ActiveSupportには、便利なライブラリがたくさんあることを再確認できた。