JSTL リファレンス

<fmt:message>
xmlns:fmt="http://java.sun.com/jsp/jstl/fmt"

SYNOPSIS

<fmt:message
key="キー名"
bundle="変数名"
var="変数名"
scope="page|request|session|application"
>
<fmt:param> * -  メッセージのフォーマットに使用するパラメータです.
key 属性が省略された場合のキー名を記述します.
</fmt:message>

説 明

適切なロケールのリソースバンドルからメッセージを参照して出力します。 <fmt:param> タグを使用することで MessageFormatJava™ API リファレンス 形式のフォーマットを行うことができます。

適切なリソースバンドルが選択されていない場合や、key 属性に 対応するリソースが存在しない場合、文字列 "???key???" が出力されます (??? が Java の文字化けと紛らわしいので注意してください)。

[注意] この機能は <c:out> と違い出力文字を XML エスケープしません。リソース定義自体は システムで静的であるため、問題があるなら作成時にエスケープしておけば 良いのですが、ユーザの入力値やデータベースから取得する値などをパラ メータとして埋め込んで使用する場合は十分に注意する必要があります。 この危険性については クロスサイトスクリプティングGoogle I'm Feeling Lucky™ (Cross Site Scripting, CSS, XSS) やスクリプトインジェクション (Script Injection) で検索してください。

属 性

key="キー名"
optional

リソースバンドルから参照するこのメッセージのキーです。 省略した場合はこのタグ内の評価結果をキーとして使用します。

このタグが <fmt:bundle> で囲まれている場合、その prefix 属性が指定されているならその接頭辞を省略して記述することができます。

値が null もしくは長さ 0 の文字列の場合、キーに対するリソースが見つからなかった ものとして動作します (この時出力されるメッセージは ?????? です)。

bundle="変数名"
optional

メッセージを参照するリソースバンドルを指定します。 これは <fmt:setBundle>var 属性で指定した名前を EL で記述します。

この属性を省略した場合は設定変数 javax.servlet.jsp.jstl.fmt.localizationContext に設定されているのリソースバンドルを使用します。これはこのタグを囲っている <fmt:bundle> や、var 属性を省略した <fmt:setBundle> のリソースバンドルを意味します。

タグが <fmt:bundle> に囲まれていない状態でこの属性を省略したり、 bundle で指定したリソースバンドルが存在しない場合、出力は ???key??? となります。

var="変数名"
optional

取得 (またはフォーマット) したメッセージ文字列を格納する変数名を指定します。 この属性を指定した場合、このタグの位置でメッセージの出力は行われません。 scope 属性を指定した場合は必須です。

scope="page|request|session|application"
optional
var 属性で指定した変数のスコープ。 page, request, session, application のいずれかを指定します。

内 容

key 属性が省略された場合のキー名を記述します。
メッセージのフォーマットに使用するパラメータです。

使用例

リソースバンドルの使用

<fmt:bundle> のサンプルで使用した リソースバンドルをここでも使用します。日本語版リソースバンドルは以下の通りです (native2ascii で変換を行う前)。
gourmet_ja.properties (変換前)
food.japanese.susi.tuna = まぐろ
food.japanese.susi.fattytuna = トロ
food.japanese.susi.abalone = あわび
food.japanese.susi.turbot = ひらめ
food.japanese.susi.congereel = あなご
food.japanese.susi.flatfish = かれい
food.japanese.susi.seaurchin = うに
food.japanese.susi.calamari = いか
food.japanese.susi.herringroe = 数の子
food.japanese.susi.octopus = たこ
リソースバンドルに定義されているリソース、定義されていないリソース、長さ 0 のキー名で それぞれ実行します。未定義のリソースに対しては ??? が付加されているのが分かります。
JSP
<fmt:bundle basename="biz.moyo.lab.resource.sample.gourmet">
  <fmt:message key="food.japanese.susi.turbot" /><br>
  <fmt:message key="food.japanese.susi.bonito" /><br>
  <fmt:message key="" /><br>
</fmt:bundle>
実行結果
ひらめ
???food.japanese.susi.bonito???
??????

フォーマットパラメータの使用

MessageFormatJava™ API リファレンス 形式のメッセージを持つリソースバンドルを作成します。
message.properties
message.greeting = hello world, {0} {1}
パラメータでフォーマットして出力を行います。
JSP
<c:set var="userName" value="moyo" />

<fmt:setBundle basename="biz.moyo.lab.resource.sample.message" />
<fmt:message key="message.greeting">
  <fmt:param>Mr.</fmt:param>
  <fmt:param><c:out value="${userName}" /></fmt:param>
</fmt:message>
実行結果
hello world, Mr. moyo
ただしプレースホルダの数に実際のパラメータ数が足りない場合 (1 つも指定しなかった場合を含む) は、残りのプレースホルダがそのまま出力されます。
JSP
<fmt:setBundle basename="biz.moyo.lab.resource.sample.message" />
  <fmt:param>Mr.</fmt:param>
<fmt:message key="message.greeting" />
実行結果
hello world, Mr. {1}

クロスサイトスクリプティング

<fmt:message> タグを使った出力は XML エスケープされないため、 プロパティファイル上で記述した HTML 書式はそのままブラウザに反映されます。 しかしパラメータを埋め込むときは注意が必要です。例えば以下は任意のエラー メッセージを出力するフォーマットですが:
JSP
errormessage = [<b>ERROR</b>] 入力値不正:{0}
このパラメータにユーザの入力を指定したらどうなるでしょうか?
JSP
<c:set var="userinput" value="<script>alert(document.cookie);</script>" />

<fmt:message key="errormessage">
  <fmt:param value="${userinput}" />
</fmt:message>
これにより以下のような HTML が出力され:
実行結果 (HTML)
[<b>ERROR</b>] 入力値不正:<script>alert(document.cookie);</script>
このユーザのセッション Cookie 奪取に成功しました。
実行結果 (画面)
[ERROR] 入力値不正:
Cross Site Scripting 自分で自分のブラウザ上のスクリプトを動かす分にはあまり問題もありません。 何が起きても困るのは自分です。しかし、もしこれがチャットや掲示板で行われ、 不特定多数のブラウザで任意のスクリプトが動かせるとしたら大変危険です。
CVS 2008/03/09