Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
134
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

Railsでパスワードの取り扱い(bcrypt 3.1.7以上)

登録

パスワードの暗号化で便利なGemのbcrypt。

Railsでの取り扱い

「password」と「password_confirmation」という項目をフォームで送ると、bcryptが勝手に暗号化して、「password_digest」というカラムに暗号化したデータを入れてくれます。

取り出しも楽なので非常に重宝します。

また、has_secure_passwordというメソッドをつかいますが、こちらで以下が行われます。
- modelに「password」、「password_confirmation」属性の追加
- 「password」、「password_confirmation」のvalidationの追加(値の空白や不一致のチェック)
- authoricateメソッドの追加

Gemファイルでbcryptを有効にする

$ vi Gemfile
-------------------------------
gem 'bcrypt', '~> 3.1.7'
-------------------------------

$ bundle install

3.1.7以上だと動きが異なっているので新しいほうの設定を入れます。

マイグレーションファイルで以下の項目を入れる。

新規は以下

migrate/yyyymmddhhmmss_create_members.rb
class CreateMembers < ActiveRecord::Migration
  def change
    create_table :members do |t|
      t.string :password_digest, null: false
    end
  end
end

追加は以下

migrate/yyyymmddhhmmss_update_members.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration
  def change
    add_column :users, :password_digest, :string
  end
end

「password_digest」というカラムがあれば自動的によしなにしてくれます。

「strong parameters」の変更

rails4.0以上だと必要な「strong parameters」の追加。
こちらは勝手にはやってくれないので、設定を追加します。

app/controllers/members_controller.rb
private
  def member_params
    params.require(:member).permit(:login_name, :email, :password, :password_confirmation)    end

ビューの作成

以下のように「password」と「password_confirmation」の
項目でFormの値を送ります。

app/views/members/login.html.erb
<div class="field"> 
  <%= f.label :password, "パスワード" %><br>
  <%= f.password_field :password %>
</div>
<div class="field">
  <%= f.label :password_confirmation, "パスワード再入力" %><br>
  <%= f.password_field :password_confirmation %>
</div>

コントローラーの変更

bcrypt-rubyで自動的にdigestを有効にするには以下の行を入れます。

app/models/member.rb
class Member < ActiveRecord::Base
  has_secure_password
end

※attr_accessorとかは入れない!!
※validatesや「password」と「password_confirmation」の一致のチェックは自動的にしてくれる。

「attr_accessor」とか入れると、その段階でpasswordの値が空になり以前のバージョンの利用方法だとはまります。

「Password can’t be blank」とかのエラーが出てしまうので、その場合はそちらを修正します。

ログイン

ログイン用のview

ログ引用のviewを以下に表示します。
form_tagでログ引用のタグを作っています。

app/views/members/login.html.erb

<%= form_tag('/members/logintmp') do %>

<%= text_field_tag 'login_name', nil, class: 'loginbox-username' %>
<%= password_field_tag 'password', nil, class:  'loginbox-password' %>

<%= submit_tag 'Login', class: 'button button-green' %>

<% end %>

ログイン用のcontroller

app/controllers/members_controller.rb
def login
    member = Member.find_by_login_name params[:login_name]
    if member && member.authenticate(params[:password])
        render :text => "Login OK"
    else
        render :text => "Login NG"
    end
end

「member = Member.find_by_login_name params[:login_name]」の行では、ログインIDがあっていればmemberのオブジェクトを返します。
間違っていればFalseを返します。

「member.authenticate(params[:password])」のメソッドではそもそもログインIDがNGのときはnilを返します。
ログインIDがあっていてパスワードがあっていればmemberのオブジェクトを返します。

この後にセッション処理などをすれば無事ログイン処理は完了です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
134
Help us understand the problem. What are the problem?