Webエンジニア初心者を抜けるための3つのバリデーション
ラブグラフのエンジニア兼CTO、横江 (@yokoe24) です。
この間インターンのかたに説明する機会があったので、こちらのブログでも。
3つのバリデーション
サーバーサイドアプリケーションの制作にあたっては
『3つのバリデーション』が必要になります。
バリデーション とは、入力された値をチェックする仕組みのことです。
データベースに変な値が保存されてアプリケーションが変な動きをしないために、
バリデーションはとても大事なものです。
そしてバリデーションは大きく3つ、
-
- フロントエンド のバリデーション
-
- サーバーサイド のバリデーション
-
- データベース のバリデーション
に分けられます。順番に見ていきましょう!
1. フロントエンドのバリデーション
フロントエンドのバリデーションは、
スマホアプリだったらスマホアプリ側の実装となりますが、
今回はWebアプリケーションを想定して、「HTMLバリデーション」と「JavaScriptバリデーション」について話します。
HTMLバリデーション
HTMLバリデーションは、例えば <input>
タグがわかりやすいです。
inputタグの属性はいろいろありますが、その中でも
-
required
:required="required"
のとき、なんらかの入力を必須とし、入力欄が空のままだといけなくする -
maxlength
: 入力できる文字数の長さを制限する(<input type="text">
などで有効) -
max
,min
: 入力できる値の最大値・最小値を指定する(<input type="number">
などで有効)
などは使う機会が多いと思います。
例えば required を設定すると、なにも記入せず送信ボタンを押すと、
以下のように表示が出て次に進むことができません。
JavaScriptバリデーション
スクショからだとわかりづらいのですが、
例えば以下は Vue.js で、Eメールの入力がない限り、
送信ボタンが disabled 状態になるようにしたものです。
https://jsfiddle.net/nekonenene/x7wjntpz/53
フロントエンドバリデーションの問題点
これらのフロントエンドバリデーションは、
ユーザー補助の観点ではいいのですが、Webアプリケーションを安全に運用するためには不完全です。
Chrome などウェブブラウザ側のデベロッパーコンソールで
HTML を書き換えて、 required
や disabled
などの条件を消してしまうことが簡単にでき、
フロントエンドバリデーションをなくした状態で送信できてしまいます。
ここを削除ボタンで消せば、
なかったことに!!!
JavaScript 側で入力内容をチェックして、
JavaScript 側で API リクエストを送るなどは、これよりは複雑でマシですが、
いちおう、JavaScript 側のコードを読めばバリデーションを無視したデータをサーバーに送りつけることが可能です。
2. サーバーサイドのバリデーション
フロントエンドバリデーションが突破されてしまったときに大事なのが、
サーバー側のバリデーションです!
ここがとっても大事です!
例えば Rails には、以下の Rails ガイドのようにモデルに様々なバリデーションを設定できます。
class Message < ApplicationRecord
validates :body, presence: true, length: { maximum: 200 }
end
のように書くことで、 Message
の body
の値として
空文字 "
や、200文字より多いテキストを入れて保存しようとしたときにエラーを吐いてくれます。
コントローラー側では以下のように書いて、
body に問題があることをユーザー側に表示させるなどをおこなうことでしょう。
def create
@message = Message.new(message_params)
if @message.save
redirect_to messages_path, notice: "メッセージを作成しました"
else
redirect_to new_message_path(@message), alert: @message.errors.full_messages.join(", ")
end
end
private
def message_params
params.require(:message).permit(:body)
end
また、モデル側に条件があるのではなく、
コントローラー側で保存しようとする内容や、保存しようとしているユーザーの権限などをチェックし、
問題があればリダイレクトするなども、サーバー側のバリデーションと言えるでしょう。
このようなサーバーバリデーションによって、
望ましくないデータが保存されることを防ぐことはとても大切です!
エンジニア初心者〜中級者にかけて、 1. のフロントエンドバリデーションの実装で満足してしまって
サーバーサイドのバリデーションをかけていないということはよくあるので、
フロントエンドバリデーションをかけた際には 「これに対するサーバーサイドバリデーションは書けていたっけな?」 と、セットのように考えることをオススメします😉
3. データベースのバリデーション
最後の砦、データベースのバリデーションです。
これは NOT NULL 制約や UNIQUE (ユニーク)制約などがよく使われると思います。
例えば Rails で以下のように create_table した場合を考えます。
create_table :products do |t|
t.string :uuid, null: false
t.string :name, null: false, default: ""
t.integer :price, null: false
t.text :description
t.timestamps
t.index :uuid, unique: true
t.index :price
end
こうすると、 price
カラムを未定義、つまり NULL の状態でデータを入れようとすると
データベースはエラーを吐き、 INSERT や UPDATE がおこなわれることを防いでくれます。
また、 uuid
カラムにはユニークインデックスが貼られているので、
すでに登録されているデータと同じ文字列の uuid を設定しようとした際もエラーを吐いてくれます。
このように、想定されていないデータをデータベース側で弾くことが可能です。
ただし、 できるだけサーバーバリデーションで防いでおいて、データベースバリデーションが実行されてDBからサーバーにエラーが返されるというのは防ぎたいものです。
けっこうDBエラーの例外処理って抜けていて 500 エラーになりがちですしね。
データベースバリデーションは、やむをえぬ事情でサーバーを介さずに
DBに直接 INSERT や UPDATE のクエリを流さないといけないときに
変なデータが入ることを防ぐためにも役立ってくれることでしょう。
(そういうこともないといいですが……)
おわりに
以上、Webアプリケーション制作に必要な3つのバリデーションについてまとめました。
特に サーバーサイドのバリデーションが超大事! ってことが伝わりましたら幸いです!
Discussion