前ページで紹介した文字列の置換の仕組みで、HTML文やSQL文で不具合の発生する記号の入力にも対応できるようになりました。しかしながら、一般的な入力フォームでは、入力できる文字数や文字のタイプに制限があるのが普通です。今回の共有ブックマークでも、テーブル作成時にそれぞれのカラムを固定長の文字列に指定したので、入力内容には文字数の制限があります。また、パスワードとニックネームは半角英数のみを登録できるようにしたいと考えています。そのため、実際にデータベースへの登録処理を行う前に、ユーザーからの入力文字列について、文字数と文字の種類をチェックする必要があります。
これらの入力内容のチェックは、入力内容を送信する前にJavaScriptを用いてクライアント側で行うことも十分可能です。しかし、悪意を持ったユーザーが想定外のパラメータを意図的に送ってくることも考えられますし、Webブラウザによっては文字数のカウントの仕組みが異なったりするので、最終的なチェックはやはりサーバ側で行うべきでしょう。
ここでは、入力された文字列の長さと、入力された文字列が半角英数のみで構成されているかどうかのチェックを行う方法を紹介します。
チェックする文字列と、許容される最小文字数と最大文字数を引数に取り、チェックした結果を整数値で返すメソッドstringLengthCheckをMyUtilに追加します。今回、この文字列のチェックをするメソッドを次のように作成しました。
/**
* 文字列中の文字数を半角文字基準でチェックする
*
* @param input チェック対象の文字列
* @param min 許容最小文字数
* @param max 許容最大文字数
* @return チェック結果。0なら許容内。負の値なら不足分。正の値なら超過分。
*/
static public int stringLengthCheck(String input, int min, int max) {
// 全角の場合の対処も考慮して、何バイト分の長さであるかを取得
int length = input.getBytes().length;
if(length < min) { // 最小文字数よりも少なかった場合
return length - min;
}
if(length > max) { // 最大文字数よりも多かった場合
return length - max;
}
return 0; // 許容内であった場合
}
このメソッドは、文字数をチェックして、許容内なら値0を、長すぎる場合は、超過分を正の値で、短すぎる場合は不足分を負の値で返します。例えば、4文字以上、10文字以下の文字列を受け付ける場合にabという文字列が入力として与えられた場合、
stringLengthCheck("ab", 4, 10);
という呼び出しで、戻り値-2が返されます。これにより、許容される長さの範囲に対して2文字分短すぎることが分かります。
Javaでは、単純にStringのlength()メソッドを用いて文字数をカウントした場合、全角1文字も長さ1としてカウントしてしまうので、ここでは、getBytes() メソッドを用いることでバイト数をカウントするようにしています。
チェックする文字列を引数に取り、文字列が半角英数のみで構成されているかどうかをboolean型の値で返すメソッドdigitAlphabetCheckをMyUtilに追加します。今回、この文字列のチェックをするメソッドを次のように作成しました。
/**
* 文字列が半角英数のみで構成されているかをチェックする
*
* @param input チェック対象の文字列
* @return チェック結果。半角英数のみなら true そうでなければ false
*/
static public boolean digitAlphabetCheck(String input) {
for(int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if( (c < '0' || c > '9') && // 数字でない
(c < 'a' || c > 'z') && // 小文字アルファベットでない
(c < 'A' || c > 'Z') // 大文字アルファベットでない
) {
return false;
}
}
return true;
}
入力された文字列に対して、1文字ずつ半角英数であるかどうかをチェックし、最後までチェックが通れば、trueを返すようになっています。
さて、上記の2つのメソッドを使用して、文字列の妥当性をチェックする仕組みをupdate.jsp に組み込みます。しかしながら、そのまま使用すると、次のように、同じような記述を何回も繰り返し行わなければならなくなってしまいます。
// タイトル文字列の長さのチェック
if(MyUtil.stringLengthCheck(title, 1, 255) < 0) {
errorMessage += "[タイトル] が指定の長さより短いです(1〜255文字)。";
} else if(MyUitl.stringLegthCheck(title, 1, 255) > 0) {
errorMessage += "[タイトル] が指定の長さを超えています(1〜255文字)。";
}
// コメント文字列の長さのチェック
// URL文字列の長さのチェック
...
文字列の置換でも行ったように、JSPからより簡単に使用できるメソッドをMyUtilクラスに追加し、それを用いて文字列の長さをチェックするようにします。今回は、次のように長さのチェックと同時にエラーメッセージの生成も行う、getLengthErrorメソッドを作成しました。
/**
* 文字列の長さをチェックし範囲を超えていたらエラーメッセージを返す
*
* @param input チェック対象の文字列
* @param min 許容最小文字数
* @param max 許容最大文字数
* @param paramName エラーメッセージ内に出力するパラメータ名
* @return エラーメッセージ。エラーが無ければ空の文字列
*/
static public String getLengthError(String input,
int min, int max, String paramName) {
String message = "";
int checkResult = stringLengthCheck(input, min, max);
if(checkResult < 0) {
message = "<li>[" + paramName +
"] が短すぎます" +
"(" + min + "〜" + max + "文字)。<br>";
} else if(checkResult > 0) {
message = "<li>[" + paramName +
"] が長すぎます" +
"(" + min + "〜" + max + "文字)。<br>";
}
return message;
}
上記のメソッド、getLengthError では、例えば、
getLengthError("abcdef", 1, 4, "パラメータ");
のように呼び出しを行うと、
<li>[パラメータ] が長すぎます(1〜4文字)。<br>
というHTML文が返されます。文字列の長さが1〜4文字の間に収まっていれば、何も返されません。
この返された文字列を使って、エラーの有無を判断するとともに、エラーの内容をそのまま取得できるようになっています。
同様に、文字列が半角英数であるかのチェックとエラーメッセージの作成を同時に行うメソッドgetDigitAlphabetErrorメソッドも次のように作成しました。
/**
* 文字列が半角英数のみで構成されているかをチェックし、
* 半角英数以外の文字が使われていたらエラーメッセージを返す
*
* @param input チェック対象の文字列
* @param paramName エラーメッセージ内に出力するパラメータ名
* @return エラーメッセージ。エラーが無ければ空の文字列
*/
static public String getDigitAlphabetError(String input, String paramName) {
String message = "";
if(!digitAlphabetCheck(input)) {
message = "<li>[" + paramName +
"] に半角英数以外の文字は使用できません。<br>";
}
return message;
}
このようなメソッドを作っておくと、update.jsp側では次のような簡単な記述で入力された文字列のチェックを行えます。
String errorMessage = "";
// 文字列の長さのチェック
errorMessage += MyUtil.getLengthError(title, 1, 255, "タイトル");
errorMessage += MyUtil.getLengthError(comment, 1, 255, "コメント");
errorMessage += MyUtil.getLengthError(url, 1, 255, "URL");
errorMessage += MyUtil.getLengthError(nickname, 1, 32, "登録者名");
errorMessage += MyUtil.getLengthError(password, 4, 16, "パスワード");
// 文字列のタイプのチェック
errorMessage += MyUtil.getDigitAlphabetError(nickname, "登録者名");
errorMessage += MyUtil.getDigitAlphabetError(password, "パスワード");
// エラーメッセージが設定されていたら
if(!errorMessage.equals("")) {
// request オブジェクトにエラーメッセージを設定
request.setAttribute("error_message", errorMessage);
// エラーページへ転送
%><jsp:forward page="input_error.jsp" /><%
}
入力項目それぞれに対して、getLengthErrorメソッドを用い、その結果として戻される文字列をerrorMessageに追加しています。エラーがなければ空の文字列が追加されるだけなので、最終的にerrorMessageが空の文字列であるかどうかでエラーの有無を確認できます。
エラーメッセージが設定されていたらrequestオブジェクトにメッセージを設定して、エラーのページ(input_error.jsp)へ転送します。
転送先のinput_error.jspでは、request オブジェクトに設定されたエラーメッセージを取得し、それを表示します。プログラムは次のようになります。
1: <%@ page contentType="text/html; charset=euc-jp" %>
2: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
3: <html>
4: <head>
5: <meta http-equiv="Content-Type" content="text/html; charset=euc-jp">
6: <title>入力エラー</title>
7: </head>
8: <body>
9: <p>「入力エラー」</p>
10: <p>
11: 入力された内容に対して次のようなエラーが発生しました。<br>
12: 再度適切な文字列を入力してください。</p>
13: <p>
14: <ul>
15: <%= request.getAttribute("error_message") %>
16: </ul>
17: <a href="javascript:history.go(-1)">戻る</a>
18: </p>
19: </body>
20: </html>
さて、以上の処理で、入力された文字列のチェックが行えるようになりました。
動作テストとして、次の画面のような入力を行ってみました。URLの欄を空のままにし、コメント文を255文字を超えるようにしました。また、登録者名には日本語を用い、パスワードは2文字だけで構成されています。すべての入力が不適切な、ちょっといじわるな例です。
上記の入力から「登録」ボタンを押した結果は次のようになりました。それぞれのエラーの内容が表示されていることが確認できます。
Copyright © ITmedia, Inc. All Rights Reserved.