管理用ページは1つのファイルで全ての機能を実現するために、次のネストした状態を処理する。
2-1. [Execute]ボタンのsubmitであれば、SQL文を実行し、結果を含んだHTMLコードを出力する(次の画面)
2-2. [Query]ボタンのsubmitであれば、SQL文を実行してデータを読み取り、その結果を含んだHTMLコードを出力する(次の画面)
2-3. SQL文の実行時例外を受けたら、例外情報を含んだHTMLコードを出力する(次の画面)
以下に管理用ページ(admin.aspxファイル)のソースコードを示す。
このファイルを、直接C:\inetpub\wwwroot\testディレクトリに作成する。
自分で打ち込んで試す場合、文字コードには、CP932(WindowsのシフトJIS。メモ帳ではANSI)、UTF-8のいずれを利用してもよい。ただし、UTF-8で記述する場合は、必ずBOMを付ける必要がある点には注意が必要である*5。エディターがUTF-8のBOMをサポートしていない場合は、一度メモ帳で開いてから上書き保存することでBOMを付けることが可能である。
*5 BOM(Byte Order Mark)とはユニコードの種類を示すためにファイルの先頭に埋め込む特殊な文字コード。本来UTF-8にはBOMは不要であるが、複数エンコーディングのサポートを単純化するためにそのような仕様としたのだと推測できる。
<%@ Page Language="C#" EnableViewState="false" Debug="true" %> ← (1)
<%@ Import namespace="System.Data.SqlClient" %>
<%@ Import namespace="System.Web" %>
<!DOCTYPE html> ← (2)
<html lang="ja">
<meta charset="utf-8">
<% ← (3)
var loggedIn = (Session["LoggedIn"] == null) ? false : (bool)Session["LoggedIn"]; ← (4)
if (!loggedIn)
{
loggedIn = Request.Form["user"] == "test" && Request.Form["pwd"] == "Test24989"; ← (5)
Session["LoggedIn"] = loggedIn;
}
if (!loggedIn)
{
%> ← (6)
<form action="admin.aspx" method="post">
<label>ユーザー<input type="text" name="user" size="16"></label>
<label>パスワード<input type="password" name="pwd" size="24"></label>
<input type="submit" value="ログイン">
</form>
<%
}
else
{
%>
<section>
<form action="admin.aspx" method="post">
<label>SQL</label><br>
<textarea name="sql" cols="80" rows="8"><%= (Request["sql"] == null) ? string.Empty : HttpUtility.HtmlEncode(Request["sql"])%></textarea> ← (7)
<div>
<input type="submit" name="execute" value="Execute">
<input type="submit" name="query" value="Query">
</div>
</form>
</section>
<section>
<%
if (!string.IsNullOrEmpty(Request["sql"])) ← (8)
{
using (var connection = new SqlConnection("Data Source=.\\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|testdb.mdf;User Instance=true"))
{
connection.Open();
using(var command = connection.CreateCommand())
{
command.CommandText = Request["sql"];
try
{
if (string.IsNullOrEmpty(Request["query"]))
{
%>
<div>
結果:<%= command.ExecuteNonQuery() %> ← (9)
</div>
<%
}
else
{
using (var reader = command.ExecuteReader()) ← (10)
{
%>
<table>
<tr>
<%
for (var i = 0; i < reader.FieldCount; i++)
{
%>
<th><%= HttpUtility.HtmlEncode(reader.GetName(i)) %></th>
<%
}
%>
</tr>
<%
while (reader.Read())
{
%>
<tr>
<%
for (var i = 0; i < reader.FieldCount; i++)
{
%>
<td><%= HttpUtility.HtmlEncode(reader[i]) %></td>
<%
}
}
%>
</table>
<%
}
}
}
catch (SqlException e)
{
%>
<div><%= HttpUtility.HtmlEncode(e.Message) %></div> ← (11)
<pre><%= HttpUtility.HtmlEncode(e.StackTrace) %></pre>
<%
}
}
connection.Close();
}
}
}
%>
</section>
</html>
*6 今となってはトリビアであるが、ASPの当初の実装には「asp.」と末尾に「.」を付けると、IISがソースそのものをテキストとして返すというデバッグ用なのか何なのかよく分からない豪快な機能があり、大問題となった(現在は当然修正されている)。参考:「[IIS] ASP スクリプトがブラウザ上に表示される」。
直接サーバー上でASPXファイルを編集した場合、エディターによっては同一ディレクトリに拡張子「.bak」や「~」が付加されたファイルが作成される。拡張子「.aspx」のファイルの読み取りをIISが保護していても、これらが保護されていなければ、内容を読み取られる危険性があることに変わりはない。
実際に試してみると分かるが、IISは拡張子「.bak」などの読み取りを既定の設定では禁止していてファイルが存在してもHTTPエラー404を返す(次の画面)。
Copyright© Digital Advantage Corp. All Rights Reserved.