Web サービスを使用する ASP は、レコードセット オブジェクトをどうしますか?
-
09-06-2019 - |
質問
現在、私は古いスパゲティコード形式で直接使用されているレコードセットオブジェクトを使用して、古典的な(古い)ASP Webページを実行しています。
管理性を向上させるために、Web サービスとして asp.net にデータ層を実装することを考えています。これは、Web サイトを asp.net にアップグレードするための最初のステップでもあります。サイト自体は今のところASPのままです…。
レコードセットのオブジェクト型を Web サービス互換の型 (配列など) に置き換える良い方法を誰かが推奨できますか?以下を何に置き換えますか?:
set objRS = oConn.execute(SQL)
while not objRS.eof
...
name = Cstr(objRS(1))
...
wend
複数のレコードセットも置き換えることができますか?私が話しているのは:
set objRS = objRs.nextRecordset
誰かがこれを経験して、推薦できますか?
@AdditionalInfo - あなたがそれを求めました:-)
初めから始めましょう。現状は:ストアドプロシージャを介してデータベースから抽出された古典的な階層コンテンツ(ヘッダー、セクション、サブセクション、コンテンツ)を含む古いASP Webサイトがあり、コンテンツページもデータベース内にあります(HTMLファイルへのリンク)。
ここで問題となるのは、ASP コードが多くの .asp ファイルに分散され、独自のデータベース接続、読み取り、書き込みを行っていることです (コンテンツを登録する必要があります)。最近、SQL インジェクション攻撃に関する問題が発生したため、私はそれを修正するために呼ばれました。
私 できた SQL インジェクションを防ぐためにすべての .asp ページを変更しますが、それは狂気の沙汰になります。そこで私はデータレイヤーを構築することを考えました。すべてのページがこのレイヤーを使用してデータベースにアクセスします。データベースのアクセスコードを修正して更新する場所を一度配置します。
この決定に至って、asp.net のアップグレードはそう遠くないと思いました。データ レイヤーに asp.net を使い始めてみてはいかがでしょうか?こうすることで、サイトをアップグレードするときに再利用できます。
そこで上記の疑問が生じます。
解決
クラシック ASP を使用したい場合は、ASP クラス経由でデータベース処理オブジェクトを作成し、そのオブジェクトを使用してレコードセットの作成を行うことをお勧めします。これにより、データベース処理コードが集中化され、SQL インジェクション攻撃を 1 か所で処理するだけで済むようになります。
簡単な例です。
Class clsDatabase
Private Sub Class_Initialize()
If Session("Debug") Then Response.Write "Database Initialized<br />"
End Sub
Private Sub Class_Terminate()
If Session("Debug") Then Response.Write "Database Terminated<br />"
End Sub
Public Function Run(SQL)
Set RS = CreateObject("ADODB.Recordset")
RS.CursorLocation = adUseClient
RS.Open SQLValidate(SQL), Application("Data"), adOpenKeyset, adLockReadOnly, adCmdText
Set Run = RS
Set RS = nothing
End Function
Public Function SQLValidate(SQL)
SQLValidate = SQL
SQLValidate = Replace(SQLValidate, "--", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, ";", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "SP_", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "@@", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " DECLARE", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "EXEC", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " DROP", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " CREATE", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " GRANT", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, " XP_", "", 1, -1, 1)
SQLValidate = Replace(SQLValidate, "CHAR(124)", "", 1, -1, 1)
End Function
End Class
これを使用するには、呼び出しを次のように変更します。
Set oData = new clsDatabase
Set Recordset = oData.Run("SELECT field FROM table WHERE something = another")
Set oData = nothing
もちろん、基本クラスを拡張して、パラメーター化されたストアド プロシージャやその他の検証などを処理することもできます。
他のヒント
まず、今週の私のお気に入りのアドバイス:Web サービスをローカル オブジェクトであるかのように扱わないでください。そうしないと、非常に高額なパフォーマンスの代償を支払うことになります。基本的に、Web アプリケーションでは次のようなことは行わないでください。
MyDataWebService ws = new MyDataWebService();
foreach(DataItem item in myData)
{
ws.Insert(item);
}
Web サービス (および SQL) への呼び出しは常に最小限に抑えることを選択する必要があります。
MyDataWebService ws = new MyDataWebService();
ws.Insert(myData); // Let the web service process the whole set at once.
Web サービス呼び出しに使用するデータ型に関しては、基本的に 2 つの選択肢があります。
- データセット
- その他すべて (配列)
Web サービスから返されるほとんどのコレクション (List<MyData> など) は、Web サービスの呼び出し中に実際に配列に変換されます。Web サービスはオブジェクト (データ + 動作) を返すのではなく、データ構造 (またはそのシーケンス) だけを返すことに注意してください。したがって、リストと配列の間にはほとんど区別がありません。
DataSet はより複雑なクラスです。独自のカスタム シリアライザーを使用し、呼び出し側アプリケーションでほぼ完全に再作成されます。このような DataSet の使用にはパフォーマンスのコストがかかるため、ほとんどのシナリオでは通常はお勧めしません。配列を使用してデータをやり取りする方が効率的になる傾向があり、率直に言って、その方が簡単です。
あなたの場合は少し異なります。すでに ADO を使用している既存のサイトを変換しているため、ADO.NET DataSet が最適なアップグレード パスである可能性があります。ADO.NET と ADO は非常に似ているため、直接更新する方が簡単になる可能性があります。それは Web サイトの構築方法によって異なります。
質問の最後の部分では、DataSet は ADO の Recordset と同様の複数のレコードセットをサポートしています。これらはデータテーブルと呼ばれます。すべての DataSet には少なくとも 1 つの DataTable があり、それらを任意の順序で読み取ることができます。
幸運を。
ASP コードで XmlHttp クラスを使用することをお勧めします。
これと同様の ASMX Web サービスが MyService.asmx にあると仮定します。
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
ASP では次のように呼び出すことができます。
Dim xhr
Set xhr = server.CreateObject("MSXML2.XMLHTTP")
xhr.Open "POST", "/MyService.asmx/HelloWorld", false
xhr.SetRequestHeader "content-type", "application/x-www-form-urlencoded"
xhr.Send
Response.Write(xhr.ResponseText)
ResponseText は次の XML 応答になります。
<string>Hello World</string>
サービスがデータのコレクションを返したと仮定すると、XPath またはその他の XML 処理技術/ライブラリを使用してそれを反復処理できます。
MSXML2 はクラシック ASP に特有のものであるため、MSXML2 についてグーグルで検索すると、おそらく具体的な質問が解決されるでしょう。
レイヤーで考える代わりに、アプリケーションを垂直方向にスライスして、それらを .net に変換してみてはいかがでしょうか。こうすることで、ばらばらの部分ではなく、機能全体を .net でコード化できます。ユーザーエクスペリエンスを改善したり機能を追加したりせずに、完全に機能するコードを置き換えることにどのようなビジネス価値があるのでしょうか?
また、直接 ado 呼び出しよりも Web サービスを諦めるパフォーマンスのトレードオフを考慮することもできます。Web サービスは、共通のスキーマにアクセスする複数の独立したアプリケーション/チームの問題に対する優れた解決策です。単一の分離されたアプリケーションの保守性が向上するわけではなく、速度が遅くなり、より複雑になるだけです。
もう 1 つの方法は、COM 相互運用機能を使用して、クラシック ASP から呼び出し可能なアセンブリを .NET で作成することです。
Visual Studio から COM 相互運用アセンブリを作成するには (例:Microsoft Visual C# 2005 Express Edition):
- 新しいクラス ライブラリ プロジェクトを作成する
プロジェクトのプロパティを開きます
- 「アプリケーション」で「アセンブリ情報...」を選択します。そして「アセンブリをCOM表示にする」を有効にします。
- [署名] で [アセンブリの署名] を有効にし、既存の厳密な名前のキー ファイルを作成または選択します。
ライブラリを作成して構築する
- COM 相互運用クラスにはデフォルトのコンストラクターが必要であり、非静的クラスとメソッドのみが公開されます。
.dll を目的のフォルダー/マシンにコピーします。
- RegAsm を使用して COM の .dll を登録する
たとえば (必要に応じて調整します):
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" "C:\path\to\assembly.dll" /tlb /codebase
- ASPからアセンブリを呼び出す
たとえば (必要に応じて調整します):
Dim obj, returnValue
Set obj = Server.CreateObject("MyProject.MyClass")
returnValue = obj.DoSomething(param1, param2)
注記:
- アセンブリは更新時に RegAsm 経由で再登録する必要があります
以下も参照してください。
SQL インジェクションは、パラメータ化された SQL クエリを使用して処理する必要があります。これにより、セキュリティ リスクが排除されるだけでなく、実行プランを毎回再計算するのではなく再利用できるため、データベースのパフォーマンスが大幅に向上します。文字列置換によってこれを処理するという提案は愚かです。VB は文字列の処理が苦手で、これらの "replace" ステートメントはパフォーマンスとメモリのコストが非常に高くなります (また、実際には ' 文字を処理するだけで済みます)
コードを .net に移動しても改善されません。ページに DB コードを含めるのは悪いことではありません。特に、開発者が数人しかいない小さなサイトについて話している場合はそうです。数千のサイトがその技術を使用して、数十億ドルの取引を処理しています。さて、パラメータ化されていない動的 SQL は悪いので、それを排除するために取り組む必要がありますが、そのためにアプリや .net を書き直す必要はありません。私はいつも、なぜ人々が .net をアプリの事実上の改良点とみなしているのか不思議に思っています。COM モデルに存在していた悪いコードや悪い習慣のほとんどは、変換中にそのまま伝播します。
真に一貫性があり、結合が最小限に抑えられた OO 設計を作成することに取り組む必要があります。あるいは、それほど悪いことではないので、今の状況をそのまま続けてください。
残念ながら、この質問は 2008 年には見られませんでした。私にとって、あなたのサイトは Justa フレームワークを使用しているようです。簡単な方法は、検索とデータ入力を urlencode に送信するように Justa コードを変更することです。私はそれを実行し、私にとって完璧に機能しました。
コードの残りの部分は、タイプ OS の SQL インジェクションやデータベースへのその他の侵入の試みを防ぐのに十分な安全性を備えています。