Rails

【Rails】正規表現で8文字以上アルファベットの大文字小文字、数字、記号を含めるようにパスワードを限定してみる

Rails

 

今回は正規表現を用いて8文字以上アルファベットの大文字小文字、数字、記号を含めるようにパスワードを設定したので紹介したいと思います。やや厳しめの設定だとは思いますが、セキュリティを強くするに越したことはないので、ぜひコピペして使ってみてください。

結論

VALID_PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)(?=.*?[\W_])[!-~]{8,}+\z/
validates :password, format: { with: VALID_PASSWORD_REGEX }

 

これを該当モデル(Userモデル等)に設定することで、8文字以上アルファベットの大文字小文字、数字、記号を含んだパスワードのみを許容することができます。

テストコード

念のためテストコードを書き、上記の正規表現が正しいか検証してみます。

# frozen_string_literal: true

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    password { 'Test1234!' }
    password_confirmation { 'Test1234!' }
  end
end
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe User, type: :model do
  context 'パスワードのバリデーションチェック' do
    it '要件通り(8文字以上でアルファベットの大文字小文字、数字、記号を含める)のパスワードを入力した場合' do
      user = build(:user)
      user.valid?
      expect(user).to be_valid
    end

    it '8文字以下の場合' do
      user = build(:user, password: 'Test12!')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '文字のみの場合' do
      user = build(:user, password: 'Testtest')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '数字のみの場合' do
      user = build(:user, password: '12345678')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '記号のみの場合' do
      user = build(:user, password: '!$%&!$%&')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '小文字を入力しない場合' do
      user = build(:user, password: 'TEST1234!')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '文字と数字のみの場合' do
      user = build(:user, password: 'Test1234')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '文字と記号のみの場合' do
      user = build(:user, password: 'Test!$%&')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end

    it '記号と数字のみの場合' do
      user = build(:user, password: '!$%&1234')
      user.valid?
      expect(user.errors[:password]).to include('は有効でありません。')
    end
  end
end

正規表現チェッカー

念には念を入れ、正規表現チェッカーでも正しい挙動を示すか確かめてみます。

↓ ↓ ↓

正規表現チェッカー

まとめ

改めて8文字以上アルファベットの大文字小文字、数字、記号を含んだパスワードのみを許容する正規表現を記載すると以下のようになります。

VALID_PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?[A-Z])(?=.*?\d)(?=.*?[\W_])[!-~]{8,}+\z/
validates :password, format: { with: VALID_PASSWORD_REGEX }

参考

Rubular

 

 

今回は正規表現を用いて8文字以上アルファベットの大文字小文字、数字、記号を含めるようにパスワードを設定しました。正規表現に慣れてくるとテストを省略しがちですが、挙動を担保するためにも必ずテストコードは書いておくことをお勧めします。