ColdFusion-開発効率を求められる今だから知りたい高性能Webアプリケーションサーバー

第5回 ColdFusionでHTMLフォームのデータを扱う

この記事を読むのに必要な時間:およそ 4 分

フォームの値にアクセスする

Formスコープの値にアクセスするには「Form.変数名」とします。⁠変数名」だけでもアクセスすることは可能ですが,Variablesスコープに同名の変数があった場合,そちらが優先して参照されてしまうので,フォームの値にアクセスすることを明示するため,⁠Form.」を変数名の先頭に付ける癖をつけましょう。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>Formスコープ</title>
<cfif StructKeyExists(Form, 'submit')>
  <cfset SetEncoding("Form", "UTF-8")>
  <cfoutput><p>フォームから送信された値:#Form.str#<p></cfoutput>
</cfif>
<form action="xssForm.cfm" method="post">
  <p>何かテキストを入力してください:<input type="text" name="str" value=""><br>
  <input type="submit" name="submit" value="送信" ></p>
</form>

フォームから送信された値を出力するにはこのようなコードを書いてしまいがちですが,このフコードはXSS(Cross-site Scripting)脆弱性を含んでおり危険です。例えば上の例をxssForm.cfmとして保存しアクセスした後,テキストフィールドに「<script type="text/javascript">alert("hello")</script>」と入力し,送信してみましょう。アラートボックスが表示されたかと思います。

図3 ⁠<script type="text/javascript">alert("hello")</script>」と入力し送信してみた例

図3 

このようにページ制作者が意図しないHTMLコードを紛れ込ませることができるような状況は危険です。何らかの値をページ中に表示させるときは,以下のように必ずHtmlEditFormat()関数を通すようにしましょう。先回解説したとおり,HtmlEditFormat()関数はHTMLで用いられる特別な文字(⁠⁠<」「&」など)をエスケープしてくれる関数です。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>Formスコープ</title>
<cfif StructKeyExists(Form, 'submit')>
  <cfset SetEncoding("Form", "UTF-8")>
  <cfoutput><p>フォームから送信された値:#HtmlEditFormat(Form.str)#<p></cfoutput>
</cfif>
<form action="non-xssForm.cfm" method="post">
  <p>何かテキストを入力してください:<input type="text" name="str" value=""><br>
  <input type="submit" name="submit" value="送信" ></p>
</form>

図4 non-xssForm.cfmで「<script type="text/javascript">alert("hello")</script>」と入力し送信してみた例

図4 non-xssForm.cfmで

URLスコープ

Formスコープ同様,クエリーストリング(例えば「http://example.jp/test.cfm?id=1234」「id=1234」の部分)にもアクセスすることができます。クエリーストリングはUrlスコープというスコープに保存されます。以下のファイルを{cf_root}/wwwroot/gihyo/5/url.cfmとして保存し,http://127.0.0.1:8500/gihyo/5/url.cfm?q=%E3%81%82でアクセスしてみましょう。

<cfprocessingdirective pageEncoding="UTF-8" />
<cfcontent type="text/html; charset=UTF-8">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>Urlスコープ</title>
<cfset SetEncoding("Url", "UTF-8")>
<cfdump var="#Url#" label="Urlスコープの中身">

図5 url.cfm?q=%E3%81%82の実行結果

図5 url.cfm

ご覧頂いて分かるとおり,UrlスコープもFormスコープ同様に構造体で,⁠Q」というキーに「あ」という値が入っているのが分かると思います。Urlスコープも変数の大文字小文字を区別しません。従って「url.cfm?q=%E3%81%82」でアクセスしても「url.cfm?Q=%E3%81%82」でアクセスしても同様の結果が得られます。

また,クエリーストリングにある値が渡されているかどうか調べるには,Formスコープの時と同様にStructKeyExists()関数を使います。例えばクエリーストリングに「q」というキーが渡されているかどうかを調べるにはStructKeyExists(Url, 'q')とします。

まとめと次回予告

今回はまずスコープという概念を学びました。CFMLテンプレート中で宣言した変数は,すべてVariablesスコープ(実態は構造体)に格納されることが分かりました。

また,フォームでPOSTされた値はFormスコープへ,クエリーストリングで渡された値はUrlスコープに格納されることが分かりました。

そして,ある名前の変数が特定のスコープに存在するかどうかを調べる方法を学びました。StructKeyExists()関数の第一引数にスコープを,第二引数に変数名を渡せば,定義されているかどうかを調べることができます。IsDefined()関数でも同様のことができますが,IsDefined()関数は参照可能な値を全て辿っていってしまうため,目的のスコープ以外で同名の変数が定義されていた場合も定義されていると返してしまうため,プログラムが意図しない動作をしてしまう可能性があることが分かりました。

次回は,ColdFusionがAdobe製品群となったことで強化されたPDF周りの機能をご紹介します。

著者プロフィール

酒井克幸(さかいかつゆき)

フリーのテクノロジーコンサルタント。サーバー選定やネットワーク設計などハードウェアレイヤーから,Webアプリケーションの実装(サーバーサイド,クライアントサイド共)などのソフトウェアレイヤーまでの幅広い経験を活かし,クライアント企業のWebアプリケーション構築支援を行っている。殊にAdobe製品(特にMacromedia)製品には精通している。

ブログcyano(シアノ)