第15回 セッションとビューステート:連載 プログラミングASP.NET ―ASP.NETによるWebアプリケーション実践開発講座― (3/3 ページ)
Webアプリケーションでは、ページをまたがってデータを保持する必要がでてくる。ASP.NETでこれを実現するためのいくつかの方法を解説。
ビューステート
次に、クライアント・サイドに情報を保存しておく方法について解説しよう。すでに述べたように、クライアント・サイドに保存する方法には、ビューステートとクッキーがある。どちらも、サーバ・リソースを消費しないというメリットや、ラウンド・トリップにかかるコストやセキュリティ面でのデメリットは共通である。しかし、クッキーには最大でも4KBytes〜8KBytes程度の少量のデータしか保存できない上、文字列しか保存できず、さらにクライアント環境によっては受信拒否されてしまう可能性もある。クライアント・サイドに保存するのであれば、永続的にクッキーに保存する場合を除けば、ビューステートを選択した方が適している場合が多いだろう。
■ViewStateプロパティ
ビューステートの使い方は、Sessionプロパティと同じく簡単だ。ビューステートは、PageクラスのViewStateプロパティを通してアクセスできる、ディクショナリ・タイプのStateBagオブジェクトである(正確には、ViewsStateプロパティはPageクラスのスーパークラスであるControlクラスから継承している)。
以下の例を見れば分かるように、Sessionプロパティと同じく、キーに文字列を指定し、値を代入すれば、キーと値が関連付けられ、保存される。格納されたデータはobject値として取り出されるためキャストが必須であること、存在しないキーを指定した場合はnull値が取り出されることもSessionプロパティと同じだ。
int counter;
ViewState["counter"] = counter;
counter = (int) ViewState["counter"];
ただし、ViewStateプロパティとSessionプロパティには大きな違いがある。Sessionプロパティには、値としてあらゆるオブジェクトを格納できるが、ViewStateプロパティは格納できるオブジェクトの型が制限されているのである。具体的には、intやstring、booleanといったプリミティブ型、それにプリミティブ型の配列(Arrayオブジェクト)とArrayListオブジェクト、Hashtableオブジェクトが標準でサポートされている。これ以外のオブジェクトを格納するには、ISerializableインターフェイスを実装するか、独自の型コンバータを実装しなければならない。
ビューステートを使ったサンプル・プログラムをリスト15.2に示す。リスト15.2はリスト15.1の「Session」を「ViewState」に置き換えただけのプログラムだが、これだけでカウンタをビューステートに保存する、リスト15.1と全く同じカウンタが実現されている。
<%@ Page Language="C#" %>
<html>
<head>
<script runat="server">
void Page_Load(object sender, EventArgs e) {
int counter = 0;
if (IsPostBack) {
if (ViewState["counter"] != null) {
counter = (int)ViewState["counter"];
counter++;
} else {
counter = 0;
}
}
lcounter.Text = counter.ToString();
ViewState["counter"] = counter;
}
</script>
</head>
<body>
<form runat="server">
<p>
<asp:Label id="lcounter" runat="server" />
<asp:Button Text="up" runat="server" />
</p>
</form>
</body>
</html>
sample02.aspxのダウンロード(sample02.zip)
sample02.aspxの実行(www.iwebmethod.netのページ)
■ビューステートのセキュリティ
ビューステートをうまく使うには、その仕組みについて少し理解しておく必要がある。本連載第2回目でWebサーバ・コントロールの自動状態管理を解説したとき、ビューステートに保存された値は、以下のようなフォームの隠しフィールドとして出力されると述べた。
<input type="hidden" name="__VIEWSTATE" value="dDwtMTA2MDQwMDUyMDt
0PHA8bDxjb3VudGVyOz47bDxpPDk+Oz4+O2w8aTwyPjs+O2w8dDw7bDxpPDE+Oz47b
Dx0PHA8cDxsPFRleHQ7PjtsPDE7Pj47Pjs7Pjs+Pjs+Pjs+UwelzTL2Lx86lYKw17K
PUk3oV3gNCg==" />
これを見るだけでは、どんな情報が記録されているか分からないが、実は暗号化されているわけではなく、base64エンコードされているにすぎないので、デコードすれば、以下のような文字列が現れる。値とそのデータ型が羅列されていることが想像できるだろう。このように、ビューステートに格納された値は、ごく簡単な処理で見られてしまうので、パスワードやクレジットカード番号のように、見られては困る情報を格納してはならない。
t<-1060400520;t<p<l<counter;>;l<i<9>;>>;l<i<2>;>;l<t<;l<i<1>;>;l<
t<p<p<l<Text;>;l<1;>>;>;;>;>>;>>;>S…
それでは、この文字列を書き換えて、再びbase64エンコードすれば、簡単にビューステートの値を詐称してポストバックできてしまうのかといえば、そんなことはない。ビューステートの末尾には、ビューステート値のハッシュコード(デフォルトではSHA1によるもの)が追加され、耐タンパー性が高められているからだ。ポストバックされたビューステート値とハッシュコードが一致しなければ、ビューステート値はすべて破棄される。もっとも、ハッシュコードも含めて改ざんされてしまえば意味がないので、ビューステートには改ざんされても致命的な影響のないデータを保存するにとどめ、大切なデータはSessionプロパティに格納して、サーバから外に出さないようにすべきだ。
Copyright© Digital Advantage Corp. All Rights Reserved.