Go言語でのユーザー入力の検証 (バリデーション)
ユーザーからの入力データが指定された形式や条件を満たしているかを確認するプロセス。
バリデーションは「何を」「なぜ」守るのか?
バリデーションの主な目的は、以下の2点を守ることです。
・データの整合性・品質
定義されたビジネスルール(例: 年齢は18歳以上、パスワードは8文字以上など)を満たさない不正なデータがデータベースに保存されるのを防ぎます。これにより、アプリケーションの動作が予期せぬエラーを起こしたり、データが壊れたりするのを防ぎます。
・アプリケーションの安全性(セキュリティ)
ユーザー入力に紛れ込んだ悪意のあるコードや不正な操作を排除し、サーバーやデータベースが攻撃されるのを防ぎます。これがセキュリティ対策としての最も重要な役割です。
なぜサーバーサイドでのバリデーションが必要なのか?
ユーザー入力のチェックは、ユーザーのブラウザ側(クライアントサイド)でも行われることがありますが、悪意のあるユーザーによって簡単に無効化されたり、ツールを使って不正なデータに改ざんされたりする可能性があるため、セキュリティ対策としては機能しずらい点があると考えます。そのため、サーバーは、どんなリクエストが来ても「信用しない」という前提で、必ず入力されたデータが正しいか(バリデーション)をチェックする必要があります。
Go言語によるバリデーションの実装
ご提示のコードは、Goで広く使われている外部ライブラリ github.com/go-playground/validator/v10 を利用した、非常にシンプルな実装例です。
package main
import (
"fmt"
"log"
"github.com/go-playground/validator/v10"
)
// 検証用の構造体(validatorパッケージを使用)
type User struct {
Name string `validate:"required,min=3,max=10"`
}
構造体タグを使ってバリデーションルールを定義できます。
required: 必須項目です(空であってはならない)。
min=3: 最小文字数は 3文字 です。
max=10: 最大文字数は 10文字 です。
func main() {
//実行テスト
fmt.Println("Hello,world!")
//validatorインスタンス化
validate := validator.New()
// 省略しない表現-実体(インスタンス)の作成New()メソッドは、validater機能を持つ新しいValidate構造体の実体を作成
//var validate *validator.Validate = validator.New()
//変数u
u := User{Name: "test"}
//実行
err := validate.Struct(u)
if err != nil {
fmt.Printf("バリデーションエラー:%v\n", err)
} else {
fmt.Println("バリデーション成功")
}
validator.New() でバリデーターのインスタンスを作成し、validate.Struct(u) メソッドで構造体 u の検証を実行します。
この例では、"test" は4文字で、ルール(3文字以上10文字以下)を満たしているため、「バリデーション成功」となります。もし u := User{Name: "t"} (1文字)だった場合、「バリデーションエラー」となります。
Hello,world!
バリデーション成功
バリデーションが防ぐ主な攻撃
適切にバリデーションを行わないと、以下のような深刻なセキュリティ攻撃の被害に遭う可能性があります。
- SQLインジェクション (SQL Injection)
- クロスサイト・スクリプティング (XSS - Cross-Site Scripting)
- バッファオーバーフロー/DoS攻撃
上記については、NEXT記事にて順に解説いたします。
参考