|
.NETエンタープライズ
Webアプリケーション開発技術大全
Sessionオブジェクト
マイクロソフト コンサルティング本部 赤間 信幸
2004/07/15 |
|
6 画面遷移制御とアプリケーションコントローラ
Webアプリケーションにおける典型的な問題点の1つに、Webサーバ側からはクライアントブラウザ上での操作を完全には制御できない、というものがある。具体的には以下のような問題が挙げられる。
・ ブラウザの「戻る」ボタンや「進む」ボタン、あるいはURL直接指定による、想定外の画面遷移 |
|
・ エンドユーザがブラウザ上で「戻る」ボタンや「進む」ボタン、あるいはURL直接指定を行うと、設計想定範囲外の画面遷移を容易に起こすことができる(図13)。 |
|
図13 Webアプリケーションにおける想定外の画面遷移 |
・ 送信ボタンの2回押しによる、データの二重送信 |
|
・ ブラウザ上でデータ送信ボタンを素早く2回クリックすると、サーバ側に2回処理要求が飛ぶ。 |
|
・ Webサーバ側ではこの2つの処理を並列処理してしまう(図14)。 |
|
図14 二重送信されたデータの並列処理 |
・ 別ウィンドウの作成による、メモリ常駐型クッキーの複製や共有 |
|
・ 例えばセッションクッキーはメモリ常駐型クッキーとして保存されているため、ブラウザのプロセスが分かれていればセッションクッキーは別々に保持される。しかし、別ウィンドウの作成(Ctrl+Nキーなど)によりブラウザ画面が開かれた場合、プロセスが同一になるためセッションクッキーが共有される(図15)※17。 |
|
・ この結果、同一セッションから想定範囲外の順序で処理要求が来る場合がある。 |
※17 この挙動はInternet Explorerの場合であるが、ブラウザの種類(NetscapeやOperaなど)によっては異なる挙動を示す。 |
|
図15 ブラウザ起動方法の違いによるクッキーの挙動の変化 |
DHTMLを利用することで、ブラウザ上での操作をある程度制約することはできる。しかしこの方法は「悪意のない人たちの操作ミスによる誤動作を防ぐ」ためのものであり、悪意のある人たちによる不正操作や捏造データの送信を防げるものではない。また、直接のURL指定を防ぐためにアドレスバーを隠すという手法もよく見られるが、セキュリティ上の危険性(不正なサイトに誘導されているか否かをエンドユーザが判断しにくくなる)を孕んでいるし、これも悪意のある人たちによる不正操作や捏造データの送信を防げるものではない。
ウィザード形式の画面進行を強制させたいアプリケーション、あるいはインターネットバンキングのような極めて高いセキュリティを要するアプリケーションなどでは、これらの問題に対する何らかの対策が求められる。どのように考えるべきだろうか?
そもそもこの問題は、Webサーバ側からではブラウザ上でのユーザ操作に対して直接的な制約をかけることができないことに起因して発生している。このため、この問題に対処するには、「Webサーバ側でクライアントブラウザの表示状態を管理する」必要がある。最も簡単な方法としては、以下のように(図16、リスト4)、Sessionオブジェクトに現在の表示画面名やその状態を保存しておき、Webサーバにデータが送信されたタイミングでこれをチェックする方法が考えられる(リスト4のサンプルでは二重押し対策は行っておらず、画面遷移の強制方法のみ示している)。
|
図16 リスト4で示す画面遷移の例 |
private void Page_Load(object sender, System.EventArgs e)
{
if (IsPostBack != false)
{
string previousPageName = (string)Session["PageName"];
string status = (string)Session["Status"];
if (previousPageName != "a.aspx" || status != "Redirect")
{
throw new ApplicationException("不正な画面遷移によりこのページへのアクセスが試みられました。");
}
Session["PageName"] = "b.aspx";
Session["Status"] = "Postback";
}
}
private void btnOK_Click(object sender, System.EventArgs e)
{
if (Page.IsValid == false) return;
// ここでビジネス処理を行う
// うまく成功したら次の画面へ遷移
Session["PageName"] = "b.aspx";
Session["Status"] = "Redirect";
Response.Redirect("c.aspx");
}
|
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If (IsPostBack <> False) Then
Dim previousPageName As String = CType(Session("PageName"), String)
Dim status As String = CType(Session("Status"), String)
If (previousPageName <> "a.aspx" Or status <> "Redirect") Then
Throw New ApplicationException("不正な画面遷移によりこのページへのアクセスが試みられました。")
End If
Session("PageName") = "b.aspx"
Session("Status") = "Postback"
End If
End Sub
Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
If (Page.IsValid = False) Then Return
' ここでビジネス処理を行う
' うまく成功したら次の画面へ遷移
Session("PageName") = "b.aspx"
Session("Status") = "Redirect"
Response.Redirect("c.aspx")
End Sub
|
|
リスト4 Sessionオブジェクトを使った画面遷移チェックのためのコード例 |
このようにWebブラウザの表示状態をSessionオブジェクトを利用して管理することで、想定した画面遷移シーケンスから外れた処理要求を遮断することができる。しかし、数10ページ程度の小規模なアプリケーションならともかく、大規模なアプリケーション開発で上記のような行き当たりばったりのコードを記述していくことは、開発生産性や保守性の観点から考えて望ましくない。よりシステマティックな対処を行うことが望ましい。
典型的な対処方法としては以下のような手法がある。アプリケーションの要件や要求レベルに応じて、適切なものを選択したり、組み合わせて利用したりするとよい。
Insider.NET 記事ランキング
本日
月間