第7章 名簿検索システムを作ろう-3
前章で、名簿検索システムを作成しました。
本章では、さらにキーワード検索機能を追加してみましょう
本章では、さらにキーワード検索機能を追加してみましょう
7-1. 検索フォームの改造
本章では、前章で作成した検索プログラムに、キーワード検索機能をプラスしてみたいと思います。
検索の操作機能は、第2ステップとして、IDのソートと性別による抽出の他に、キーワード検索を追加します。
検索の操作機能は、第2ステップとして、IDのソートと性別による抽出の他に、キーワード検索を追加します。
■ 名簿検索システム「仕様」(第2ステップ)
設計項目 | 内容 |
---|---|
検索機能 |
1. IDソート(昇順/降順) 2. 性別による抽出 3. キーワード検索 |
フォーム name/value値 |
1. IDソート : name「id」, value:昇順「1」降順「2」 2. 性別 : name「sex」, value:両方「0」, 男性のみ「1」, 女性のみ「2」 3. キーワード : name「word」 |
文字コード | UTF-8 |
検索プログラム名 | member2.cgi |
上記の「仕様」に基づき、データベース検索のための入力フォームを変更します。
HTMLの文字コードは、同様にUTF-8です。
ファイル名はindex.htmlで保存することにします。
ファイル名はindex.htmlで保存することにします。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>名簿データベース</title> <style> table { border-collapse:collapse; margin:1em 0; } td,th { border:1px solid #555; padding:8px; } </style> </head> <body> <form action="member2.cgi"> <table> <tr> <td>ソート</td> <td> <input type="radio" name="sort" value="1" checked>ID順(昇順) <input type="radio" name="sort" value="2">ID順(降順) </td> </tr><tr> <td>男女別</td> <td> <input type="radio" name="sex" value="0" checked>両方 <input type="radio" name="sex" value="1">男性のみ <input type="radio" name="sex" value="2">女性のみ </tr><tr> <td>キーワード</td> <td><input type="text" name="word" size="25"></td> </td> </tr> </table> <input type="submit" value="検索"> </form> </body> </html>
7-2. 検索プログラムの改造
キーワード検索の追加にあたって、ポイントは二点あります。
第1には、キーワード検索にあたり、検索対象のカラムは、「名前 (name)」と「ふりがな (kana)」にします。
したがって、select文は「部分一致」になるため、キーワードの変数を$wordとしたとき、次のような構文になります。
第1には、キーワード検索にあたり、検索対象のカラムは、「名前 (name)」と「ふりがな (kana)」にします。
したがって、select文は「部分一致」になるため、キーワードの変数を$wordとしたとき、次のような構文になります。
select * from member name like '%$word%' or kana like '%$word%';上記の構文をベースに、ID順のソートと性別抽出の条件を組み合わせます。
ポイント-1
検索対象のカラム(複数)を定義して、select文へはlike句をorで結ぶ。
検索対象のカラム(複数)を定義して、select文へはlike句をorで結ぶ。
第2には、セキュリティ上の汚染チェックです。キーワード検索の文字列は日本語になるため、危険な文字列だけを排除する必要があります。
キーワード検索のための入力値については、排除する記号を次のとおりとします。
キーワード検索のための入力値については、排除する記号を次のとおりとします。
排除する文字 (注意すべき特殊記号)
[タブ] [改行] [スペース] ! " # $ % & \ ' ( ) * + , - . / : ; < > = ? @ [ ] \ ^ _ ` { } | ~
[タブ] [改行] [スペース] ! " # $ % & \ ' ( ) * + , - . / : ; < > = ? @ [ ] \ ^ _ ` { } | ~
参考サイト :
セキュアプログラミング講座
> コマンド注入攻撃対策
ポイント-2
特に日本語等の引数をselect文へ定義する場合は、注意すべき特殊記号を排除する。
特に日本語等の引数をselect文へ定義する場合は、注意すべき特殊記号を排除する。
以上を留意して、第2ステップの検索プログラムを次のように記述してみます。
文字コードは同様にUTF-8になり、ファイル名はmember2.cgiとします。
上記のプログラムは、以下の名簿検索フォームから試すことができます。
文字コードは同様にUTF-8になり、ファイル名はmember2.cgiとします。
#!/usr/local/bin/perl # 名簿検索システム-2 # created by (c)kentweb use strict; use CGI::Carp qw(fatalsToBrowser); use DBI; use CGI; my $cgi = new CGI; # 引数を受取り my $sort = $cgi->param('sort'); my $sex = $cgi->param('sex'); my $word = $cgi->param('word'); # 引数の正当性 $sort =~ s/\D//g; $sex =~ s/\D//g; $word =~ s/[<>&"'\r\s!#$\%()*+,\-.\/:;=?@\[\]\\^_`{}|~]//g; # select文 my $select = "select * from member"; # 性別条件 my $flg; if ($sex == 1) { $flg++; $select .= " where sex = '男'"; } elsif ($sex == 2) { $flg++; $select .= " where sex = '女'"; } # キーワード if ($word ne '') { if ($flg) { $select .= " and ("; } else { $select .= " where"; } $select .= " name like '%$word%' or kana like '%$word%'"; $select .= ")" if ($flg); } # ソート条件 if ($sort == 1) { $select .= " order by id asc;"; } else { $select .= " order by id desc;"; } # DB接続 my $dbh = DBI->connect("dbi:SQLite:dbname=member.db"); # 命令実行 my $sth = $dbh->prepare($select); $sth->execute; header(); print <<EOM; <div align="center"> <table> <tr> <th>会員ID</th> <th>名前</th> <th>ふりがな</th> <th>性別</th> <th>住所</th> </tr> EOM # データ抽出 while (my ($id,$name,$kana,$sex,$addr) = $sth->fetchrow_array) { print qq|<tr><td>$id</td>|; print qq|<td>$name</td>|; print qq|<td>$kana</td>|; print qq|<td>$sex</td>|; print qq|<td>$addr</td></tr>\n|; } # 完了 $sth->finish(); undef $sth; $dbh->disconnect; print <<EOM; </div> </body> </html> EOM #----------------------------------------------------------- # ヘッダー #----------------------------------------------------------- sub header { print <<EOM; Content-type: text/html; charset=utf-8 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>名簿データベース</title> <style> table { border-collapse:collapse; margin:1em 0; } td,th { border:1px solid #555; padding:8px; } th { background:#ccc; } </style> </head> <body> EOM }
7-3. 本番サーバ設置の場合
ディレクトリ/ファイルの設置方法ですが、前章ではXAMPP環境の設置例を示しましたが、実際の本番環境へ設置する場合の設置例について解説します。
本番環境で特に気を付けることとしては、名簿データベースである「member.db」を外部からダウンロードされないように注意することが必要です。
本番環境で特に気を付けることとしては、名簿データベースである「member.db」を外部からダウンロードされないように注意することが必要です。
パターン1
基本は、次のように、公開ディレクトリであるホームディレクトリと「平行の位置」にデータ用ディレクトリを作成して、外部から直接アクセスできない位置に置きます。
かっこ内はパーミッション値です。
基本は、次のように、公開ディレクトリであるホームディレクトリと「平行の位置」にデータ用ディレクトリを作成して、外部から直接アクセスできない位置に置きます。
かっこ内はパーミッション値です。
/var/www/ ← ログインする位置 | +-- data / member.db [644] ← 外部からアクセスされない位置に置く | +-- html / ... ホームディレクトリ | +-- member / index.html .......... 検索フォーム member2.cgi [755] ... 検索プログラム
パターン2
サーバによっては、ログインする位置がホームディレクトリになっているところもあります。
その場合には、すべてが公開ディレクトリとなるため、パターン1の配置はできません。
このようなサーバでは、直下にデータ用ディレクトリを作成して、アクセスを排除するための.htaccessを一緒に置きます。
サーバによっては、ログインする位置がホームディレクトリになっているところもあります。
その場合には、すべてが公開ディレクトリとなるため、パターン1の配置はできません。
このようなサーバでは、直下にデータ用ディレクトリを作成して、アクセスを排除するための.htaccessを一緒に置きます。
/var/www/html/ ← ログインする位置(ホームディレクトリ) | | +-- member / index.html .... 検索フォーム | member2.cgi [755] ... 検索プログラム | +-- data / .htaccess ......... ディレクトリ内へのアクセスを排除 member.db [644] ..... データファイル.htaccessファイルの中身は、次の一文を入力したものとします。末尾は改行を入力してください。
deny from all