使用 recordset 对象处理结果
发布时间:2006-5-29 9:12:01   收集提供:shendata

为了检索数据、检查结果和更改数据库,ado 提供了 recordset 对象。正如名字所示,“recordset”对象具有用来检索和显示数据库行(或叫“记录”)的功能,这取决于您的查询约束条件。“recordset”对象保留由查询返回的每一条记录的位置,这样就能使您查看所有的结果,每次一条。

检索记录集
成功的 web 数据应用程序既使用“connection”对象来建立链接,又使用“recordset”对象来处理返回的数据。通过综合使用这两种对象的一些特殊功能,开发出的数据库应用程序几乎可以执行所有的数据处理任务。例如,下面的服务器端脚本使用“recordset”对象执行 sql 的 select 命令。此 select 命令用来检索基于查询约束条件的信息集。此查询也包含 sql where 子句,用来将查询限制到一个指定的标准。在本例中,where 子句将查询限制在 customers 数据库表中姓氏字段包含 smith 的所有记录。

<%
'建立数据源连接
strconnectionstring = "provider=microsoft.jet.oledb.4.0;data source=c:\data\employees.mdb"
set cnn = server.createobject("adodb.connection")
cnn.open strconnectionstring

'例示 recordset 对象
set rstcustomers = server.createobject("adodb.recordset")

'使用 open 方法打开记录集
'并使用通过 connection 对象建立的连接。
strsql = "select firstname, lastname from customers where lastname = 'smith' "
rstcustomers.open strsql, cnn

'遍历记录集和显示结果
'并使用 movenext 方法递增记录位置。
set objfirstname = rstcustomers("firstname")
set objlastname = rstcustomers("lastname")
do until rstcustomers.eof
response.write objfirstname & " " & objlastname & "<br>"
rstcustomers.movenext
loop

%>
注意,在上例中,“connection”对象建立数据库连接,而“recordset”对象使用同一连接从数据库中检索结果。当需要精确配置建立数据库链接的方式时,该方法非常有用。例如,如果要指定在连接中止之前的时间延迟,可能需要使用“connection”对象设置该属性。但是,如果只想使用 ado 的默认连接属性建立连接,您可以使用“recordset”对象的“open”方法来建立链接:

<%
strconnectionstring = "provider=microsoft.jet.oledb.4.0;data source=c:\data\employees.mdb"
strsql = "select firstname, lastname from customers where lastname = 'smith' "
set rstcustomers = server.createobject("adodb.recordset")

'使用 open 方法打开连接
'并使用通过 connection 对象建立的连接。
rstcustomers.open strsql, strconnectionstring

'遍历记录集,显示结果,
'并使用 movenext 方法递增记录位置。
set objfirstname = rstcustomers("firstname")
set objlastname = rstcustomers("lastname")
do until rstcustomers.eof
response.write objfirstname & " " & objlastname & "<br>"
rstcustomers.movenext
loop
%>
当使用“recordset”对象的“open”方法来建立连接时,实际上正在隐含地使用“connection”对象保护链接的安全。详细信息,请参阅 microsoft activex 数据对象 (ado) 文档,可在 microsoft universal data access web 站点 http://www.microsoft.com/data/ 上找到该文档。

注意 要明显提高 asp 数据库应用程序的性能,请考虑在“应用程序”状态中高速缓存记录集。详细信息,请参阅高速缓存数据。

统计记录集中返回的记录数有时候很有用。“recordset”对象的“open”方法使您能够指定可选的光标参数,以确定潜在提供者检索和浏览记录集的方法。通过给用来执行查询的语句添加 adopenkeyset 光标参数,可以使客户端应用程序完全地浏览记录集。因此,应用程序可使用 recordcount 属性精确地统计记录集中的记录数。请参看下面的示例:

<%
set rs = server.createobject("adodb.recordset")
rs.open "select * from neworders", "provider=microsoft.jet.oledb.3.51;data source='c:\customerorders\orders.mdb'", adopenkeyset, adlockoptimistic, adcmdtext

'使用 recordset 对象的 recordcount 属性进行统计。
if rs.recordcount >= 5 then
response.write "我们已经收到下面" & rs.recordcount & "个新订单<br>"

do until rs.eof
response.write rs("customerfirstname") & " " & rs("customerlastname") & "<br>"
response.write rs("accountnumber") & "<br>"
response.write rs("quantity") & "<br>"
response.write rs("deliverydate") & "<br><br>"
rs.movenext
loop

else
response.write "订单数少于 " & rs.recordcount & "。"
end if

rs.close
%>
使用 command 对象改善查询
使用 ado 的 command 对象执行查询的方式与使用“connection”和“recordset”对象执行查询的方式一样,但是使用“command”对象可以准备(或编译)对数据库源的查询,然后使用各种不同的值重复发送此查询。用这种方法编译查询的好处在于,当您需要重新发布修改过的已有查询时,可以大大地减少发布时间。另外,还可以留下部分 sql 查询不进行定义,用到了在执行之前改变查询部分的选项。

“command”对象的“parameters”集合可以使您避免每次重新发布查询时都要重建查询的麻烦。例如,如果您需要定期更新基于 web 的库存系统的供应和费用信息,就可以按照下面的方式预定义查询:

<%
'使用 connection 对象打开连接注意,command 对象
'并不具有用来建立连接的 open 方法。
strconnectionstring = "provider=microsoft.jet.oledb.4.0;data source=c:\data\inventory.mdb"
set cnn = server.createobject("adodb.connection")
cnn.open strconnectionstring

'例示 command 对象;使用 activeconnection 属性将
'连接附加到 command 对象上。
set cmn= server.createobject("adodb.command")
set cmn.activeconnection = cnn

'定义 sql 查询。
cmn.commandtext = "insert into inventory (material, quantity) values (?, ?)"

'在 command 对象首次执行之前保存在 commandtext 属性
'中指定的查询的预备(或预编译)版本。
cmn.prepared = true

'定义查询参数配置信息。
cmn.parameters.append cmn.createparameter("material_type",advarchar, ,255 )
cmn.parameters.append cmn.createparameter("quantity",advarchar, ,255 )

'定义并执行第一个插入操作 。
cmn("material_type") = "日光灯泡"
cmn("quantity") = "40"
cmn.execute ,,adcmdtext + adexecutenorecords

'定义并执行第二个插入操作。
cmn("material_type") = "保险丝"
cmn("quantity") = "600"
cmn.execute ,,adcmdtext + adexecutenorecords
.
.
.
%>
要点 ado 参数(如 adcmdtext)是一些简单变量,这意味着在使用数据访问脚本中的 ado 参数之前需要先定义参数值。由于 ado 使用了大量的参数,因此通过“组件类型库”来定义参数更容易些,组件类型库是包含所有 ado 参数和常量定义的文件。有关实施 ado 类型库的详细信息,请参阅使用变量和常量主题中的使用常量部分。

在上例中,您将注意到脚本使用不同的值重复构建和重新发布 sql 查询,但并没有重新定义并重新发送查询到数据库源中。使用“command”命令编译查询也有如下优点:可避免当将字符串和变量连接成 sql 查询时引起问题。特别地,使用“command”对象的“parameter”集合,您可以避免那些与定义特定类型字符串、日期和时间变量相关的问题。例如,包含单引号 (') 的 sql 查询值可能导致查询失败:

strsql = "insert into customers (firstname, lastname) values ('robert','o'hara')"
注意,姓氏“o'hara”包含一个单引号,这与用来表示 sql values 关键字中数据的单引号冲突。通过将查询值约束为“command”对象参数可以避免此类问题。

合并 html 表单和数据库访问
包含 html 表单的 web 页可允许用户远程查询数据库并检索指定的信息。使用 ado 您可以创建出非常简单的用来收集用户表单信息的脚本、创建自定义的数据库查询并将信息返回给用户。使用 asp 的“request”对象,您可以检索输入到 html 表单中的信息并将这些信息嵌入到 sql 语句中。例如,下面的脚本块会将由 html 表单提供的信息插入到表中。脚本使用“request”对象的“form”集合来收集用户信息。

<%
'使用 connection 对象打开连接command 对象
'并不具有用来建立连接的 open 方法。
strconnectionstring = "provider=microsoft.jet.oledb.4.0;data source=d:\companycatalog\seeds.mdb"
set cnn = server.createobject("adodb.connection")
cnn.open strconnectionstring

'例示 command 对象
'并使用 activeconnection 属性附加对象
'连接附加到 command 对象上。
set cmn= server.createobject("adodb.command")
set cmn.activeconnection = cnn

'定义 sql 查询。
cmn.commandtext = "insert into myseedstable (type) values (?)"

'定义查询参数配置信息。
cmn.parameters.append cmn.createparameter("type",advarchar, ,255)

'指派输入值并执行更新。
cmn("type") = request.form("seedtype")
cmn.execute ,,adcmdtext + adexecutenorecords
%>
有关表单和使用 asp“request”对象的详细信息,请参阅处理用户输入。

管理数据库连接
设计完善的 web 数据库应用程序(如服务成千上万个客户的联机订购输入应用程序)的一个主要挑战就是如何正确管理数据库连接。打开并维护数据库连接,尤其是当没有信息传输时也要打开和维护,会严重消耗数据库服务器的资源并导致连接性问题。设计良好的 web 数据库应用程序可重复利用数据库连接并补偿因网络通信量导致的延迟。

超时连接
数据库服务器当活动突然激增时会产生积压,同时大大增加建立数据库连接所需的时间。因此,过多的连接延迟会降低数据库应用程序的性能。

使用“connection”对象的“connectiontimeout”可以限制应用程序在放弃连接尝试并发布错误消息之前等待的时间数。例如,下面的脚本将“connectiontimeout”属性设置为在取消连接尝试之前等待 20 秒。

set cnn = server.createobject("adodb.connection")
cnn.connectiontimeout = 20
cnn.open "provider=microsoft.jet.oledb.4.0;data source=c:\data\inventory.mdb"

“connectiontimeout”属性默认为 30 秒。

注意 在将“connectiontimeout”属性并入数据库应用程序之前,请确保您的连接提供者和数据源支持该属性。

共用连接
连接池可使您的 web 应用程序使用“池”中的连接,“池”指的是包含许多不需要重新建立的自由连接的容器。创建连接并放入连接池中后,应用程序可以重复使用该连接而不必执行连接进程。这可明显地提高性能,特别是在应用程序通过网络连接或需要重复连接和断开的情况下更是如此。另外,共用的连接可被多个应用程序重复使用。

ole db 会话池
ole db 具有一个共用特性,称为“会话池”,用来提高大型 web 数据库应用程序的活动性能。会话池保护连接安全和一些其他属性。共用的连接只在连接两端提出匹配的请求时才可重新使用。默认情况下,microsoft sql server 和 oracle 的 ole db 提供者支持会话池。这意味着并不需要配置应用程序、服务器或数据库即可使用会话池。然而,如果提供者默认情况下不支持会话池,则需要创建注册表设置以启用会话池。关于会话池的详细信息,请参阅 ole db 2.0 software development kit (sdk) 文档。

odbc 连接池
如果希望 odbc 驱动程序分享连接池,您必须配置特定的数据库驱动程序,然后在 windows 注册表中设置驱动程序的“cptimeout”属性。“cptimeout”属性确定连接在连接池中保留的时间长度。如果连接在池中保留的时间超过“cptimeout”设置的持续时间,连接将关闭并从池中删除。“cptimeout”的默认值是 60 秒。

通过创建带有下面设置的注册表键值,您可以有选择地设置“cptimeout”属性以启用特定 odbc 数据库驱动程序的连接池:

\hkey_local_machine\software\odbc\odbcinst.ini\driver-name\cptimeout = 超时数
(reg_sz, 以秒为单位)

例如,下面的键值将 sql server 驱动程序的连接池超时设置为 180 秒(3 分钟)。

\hkey_local_machine\software\odbc\odbcinst.ini\sql server\cptimeout = 180
注意 默认情况下,web 服务器激活 sql server 的连接池并将“cptimeout”设置为 60 秒。

使用跨多页的连接
虽然可以通过将连接储存在 asp 的“application”对象中来重复使用跨多页的连接,但这样做可能导致不必要地保持打开的连接,并且可能损害使用连接池的优势。如果有许多用户需要连接到同一 asp 应用程序,一种更好的方法是重复使用跨多个 web 页的数据库连接字符串,只需将字符串放置到 asp 的“application”对象中即可。例如,您可以在 global.asa 文件的 application_onstart 事件过程中指定连接字符串,如下面的脚本所示:

application("connectionstring") = "provider=microsoft.jet.oledb.4.0;data source=c:\data\inventory.mdb"

然后在每一个访问数据库的 asp 文件中,写入

<object runat=server id=cnn progid="adodb.connection"></object>
以创建该页的连接对象实例,并使用脚本

cnn.open application("connectionstring")
打开该连接。要关闭连接,在该页的末尾可以使用

cnn.close
在个别用户需要重复使用跨多个 web 页连接的情况下,您将发现使用“session”对象储存连接字符串比使用“application”对象更具优势。

关闭连接
要充分利用连接池,请尽可能显式关闭数据库连接。默认情况下,连接在脚本执行完后终止。然而,通过显式关闭脚本已不再需要的连接,您可以减少对数据库服务器的要求,并使得其他用户可以使用该连接。

可以使用“connection”对象的“close”方法显式终止“connection”对象和数据库之间的连接。下面的脚本将打开和关闭连接:

<%
strconnectionstring = "provider=microsoft.jet.oledb.4.0;data source=c:\data\inventory.mdb"
set cnn = server.createobject("adodb.connection")
cnn.open strconnectionstring
cnn.close
%>
dalongleng 2006-02-14 01:50
文章简介:本文将为大家介绍在Microsoft Win系列SERVER (IIS5.0、IIS6.0)中如何简单快速解决ASP中危险组件对WEB服务器系统的安全威胁之详细防范设置步骤;读完本文,您将可以使您的网站服务器免去ASP木马、Webshell所面对的提升权限、甚至危害到系统安全的威胁。

本文作者:李泊林/LeeBolin 资深系统工程师、专业网络安全顾问。 已成功为国内多家大中型企业,ISP服务商提供了完整的网络安全解决方案。尤其擅长于整体网络安全方案的设计、大型网络工程的策划、以及提供完整的各种服务器系列安全整体解决方案 。

ASP木马、Webshell之安全防范解决办法正文内容:
注意:本文所讲述之设置方法与环境:适用于Microsoft Windows 2000 Server/Win2003 SERVER | IIS5.0/IIS6.0

1、首先我们来看看一般ASP木马、Webshell所利用的ASP组件有那些?我们以海洋木马为列:
<object runat="server" id="ws" scope="page" classid="clsid:72C24DD5-D70A-438B-8A42-98424B88AFB8">
</object>
<object runat="server" id="ws" scope="page" classid="clsid:F935DC22-1CF0-11D0-ADB9-00C04FD58A0B">
</object>
<object runat="server" id="net" scope="page" classid="clsid:093FF999-1EA0-4079-9525-9614C3504B74">
</object>
<object runat="server" id="net" scope="page" classid="clsid:F935DC26-1CF0-11D0-ADB9-00C04FD58A0B">
</object>
<object runat="server" id="fso" scope="page" classid="clsid:0D43FE01-F093-11CF-8940-00A0C9054228">
</object>

shellStr="Shell"
applicationStr="Application"
if cmdPath="wscriptShell"
set sa=server.createObject(shellStr&"."&applicationStr)
set streamT=server.createObject("adodb.stream")
set domainObject = GetObject("WinNT://.")

以上是海洋中的相关代码,从上面的代码我们不难看出一般ASP木马、Webshell主要利用了以下几类ASP组件:
① Wscript.Shell (classid:72C24DD5-D70A-438B-8A42-98424B88AFB8)
② Wscript.Shell.1 (classid:F935DC22-1CF0-11D0-ADB9-00C04FD58A0B)
③ Wscript.Network (classid:093FF999-1EA0-4079-9525-9614C3504B74)
④ Wscript.Network.1 (classid:093FF999-1EA0-4079-9525-9614C3504B74)
⑤ FileSystem Object (classid:0D43FE01-F093-11CF-8940-00A0C9054228)
⑥ Adodb.stream (classid:{00000566-0000-0010-8000-00AA006D2EA4})
⑦ Shell.applicaiton....

hehe,这下我们清楚了危害我们WEB SERVER IIS的最罪魁祸首是谁了!!开始操刀,come on...

2:解决办法:

① 删除或更名以下危险的ASP组件:
Wscript.Shell、Wscript.Shell.1、Wscript.Network、Wscript.Network.1、adodb.stream、Shell.application
开始------->运行--------->Regedit,打开注册表编辑器,按Ctrl+F查找,依次输入以上Wscript.Shell等组件名称以及相应的ClassID,然后进行删除或者更改名称(这里建议大家更名,如果有部分网页ASP程序利用了上面的组件的话呢,只需在将写ASP代码的时候用我们更改后的组件名称即可正常使用。当然如果你确信你的ASP程序中没有用到以上组件,还是直
接删除心中踏实一些^_^,按常规一般来说是不会做到以上这些组件的。删除或更名后,iisreset重启IIS后即可升效。)
[注意:由于Adodb.Stream这个组件有很多网页中将用到,所以如果你的服务器是开虚拟主机的话,建议酢情处理。]

② 关于 File System Object (classid:0D43FE01-F093-11CF-8940-00A0C9054228)即常说的FSO的安全问题,如果您的服务器必需要用到FSO的话,(部分虚拟主机服务器一般需开FSO功能)可以参照本人的另一篇关于FSO安全解决办法的文章:Microsoft Windows 2000 Server FSO 安全隐患解决办法。如果您确信不要用到的话,可以直接反注册此组件即可。

③ 直接反注册、卸载这些危险组件的方法:(实用于不想用①及②类此类烦琐的方法)

卸载wscript.shell对象,在cmd下或直接运行:regsvr32 /u %windir%\system32\WSHom.Ocx

卸载FSO对象,在cmd下或直接运行:regsvr32.exe /u %windir%\system32\scrrun.dll

卸载stream对象,在cmd下或直接运行: regsvr32 /s /u "C:\Program Files\Common Files\System\ado\msado15.dll"

如果想恢复的话只需要去掉 /U 即可重新再注册以上相关ASP组件例如:regsvr32.exe %windir%\system32\scrrun.dll

④ 关于Webshell中利用set domainObject = GetObject("WinNT://.")来获取服务器的进程、服务以及用户等信息的防范,大家可以将服务中的Workstation[提供网络链结和通讯]即Lanmanworkstation服务停止并禁用即可。此处理后,Webshell显示进程处将为空白。

3 按照上1、2方法对ASP类危险组件进行处理后,用阿江的asp探针测试了一下,"服务器CPU详情"和"服务器操作系统"根本查不到,内容为空白的。再用海洋测试Wsript.Shell来运行cmd命令也是提示Active无法创建对像。大家就都可以再也不要为ASP木马危害到服务器系统的安全而担扰了。

当然服务器安全远远不至这些,这里为大家介绍的仅仅是本人在处理ASP木马、Webshell上的一些心得体会。在下一篇中将为大家介绍如何简简单单的防止别人在服务器上执行如net user之类的命令,防溢出类攻击得到cmdshell,以及执行添加用户、改NTFS设置权限到终端登录等等的最简单有效的防范方法。

dalongleng 2006-02-14 01:50
Microsoft已经紧密地集成了IIS和COM+的功能,这使我们能非常容易地在事务性Web页面编程中利用事务处理应用程序。有许多不同方式集成COM+和IIS的事务特性,这些例子包括:
  事务性ASP。
  ASP 中的ObjectContext。
  事务性事件。
  开发者可以在使用IIS和COM+的应用程序中使用一个或多个这些特性。因为它们是紧密集成的,开发者只进行少量的工作,就能充分利用这些服务。事实上,在COM+ 中ObjectContext封装了一个事务,可以直接用于事务中的ASP页面。
19.4.1 事务性ASP
  由于IIS 4.0和MTS的集成,开发者可以在一个事务中包含ASP脚本。这些ASP网页可以包含对服务器组件的调用,这些组件也将参与相同的事务。同所有的事务一样,如果事务的任一部分失败,将回滚整个事务。事务性ASP脚本所增加的优点就是使得把多个组件绑定到单个事务中变得简单化。
  当处理一个终止的事务时,使用事务性脚本有一个问题。通过数据库的资源管理器访问数据库产生的改变将被自动地回滚,然而, COM+不能回滚脚本自身产生的变化。例如,使用脚本产生的任何变化,如对Session或Application变量的改变,将不会自动地回滚。以后你将看到如何使用事务性事件通知事务已经终止。当处理这个事件时,能手工地回滚COM+不能自动回滚的变化。这种限制的原因是COM+事务只能回滚与MS DTC相容的服务产生的变化。
  在IIS 5.0中有一个新特性。开发者具有使得一个事务跨越多个ASP脚本网页的能力。这归功于在Server对象上新增的Execute和Transfer方法。
  然而,正常情况下,单个事务的所有处理可以在单个ASP网页中完成。例如,如果一个应用程序有一个组件从一个帐户中提款,而另一个组件在一个帐户中存款。为了把资金从一个帐户转到另一个帐户,创建ASP脚本,利用提款组件从帐户中取出资金,使用存款组件把资金存入新的帐户。将所有这些功能放入一个事务性ASP网页中,如果事务过程的任一部分失败,就回滚所有的变化,帐户余额回到其初始值。
  为声明一个网页是事务性的,使用下列指令:
  <%@ TRANSACTION=value %>
  对TRANSACTION指令可能的设置有:
  Disabled:告诉COM+不希望在事务中涉及组件。
  Requires_New:即使已存在一个事务,也启动一个新的事务。
  Required:如果不存在事务就启动一个新的,如果存在就参与到其中。
  Supported:不启动一个事务,但是如果事务已经存在就参与它。
  Not_Supported:即使存在事务,也不参与事务 。
  这些值与使用组件服务浏览器为每个组件设置的Transaction Support属性的作用相同。
  TRANSACTION指令必须处在ASP页面脚本的第一行,通常由LANGUAGE指令包含。如果这之前在页面中有任何内容,将产生脚本错误。如同组件中的事务一样,如果到达代码的最后一行,还没有提交或终止,则COM+假定提交,并把变化写入磁盘。另外,由页面调用的每个对象能够使用同一ASP页面的ObjectContext对象参与事务,通常就是这么做的。
19.4.2 事务性ASP中的ObjectContext对象
  当编写一个事务性ASP脚本时,你可能想直接影响脚本的事务的结果。像为事务编写的组件一样,ASP页也能利用ObjectContext对象。自从发表了ASP 2.0以后,就可以利用这个对象,它为开发者需要的所有事务处理例程提供功能。服务器组件参与事务时访问的就是这个对象,它包含SetAbort和SetComplete方法。
  下列代码显示了在一个事务性Web页中如何实例化两个COM对象和一个事务,并在这两个对象上调用一个方法。
  注意,页面顶部的事务设置表明请求一个事务。正是该设置使该页面像COM组件一样参与同一事务。事实上,只要COM组件的Transaction Support属性为Required或Supported,它们就变成由ASP页启动的事务的一部分。


  随着ASP页执行,调用每个COM类的一个方法。当执行每个方法时,其返回值用于决定处理是否成功。如果任一方法返回一个非零值, ASP页务。否则, ASP页将提交事务并将变化存入磁盘。
  这个例子的要点是所有的方法调用随着ASP页面一调用ObjectContext对象中的SetAbort方法,回滚事起进入到同一事务中。
  上述的例子还可以改写,使得COM组件中的方法从内部调用SetComplete和SetAbort方法。这将从ASP页中删除一些逻辑,并嵌入到COM组件中。用这种方式编写事务的唯一问题是ASP页不知道将要提交还是终止事务。然而,这可以通过实现事务事件来解决。
19.4.3 事务事件
  ASP页也具有侦听COM+的能力,可以了解事务何时将提交或终止。这是通过在COM+提交或终止事务前IIS调用两个例程来实现的。这两个方法称为O Transaction Commit和On TransactionAbort。
  OnTransactionCommit方法在COM+提交事务之前、准备阶段之后被触发。只要事务中没有任何部分终止,将触发OnTransactionCommit例程(事件),提交事务。如果事务被终止,则触发OnTransactionAbort事件:

  同大多数事务性ASP页一样,上述例子的开始外声明它要求一个事务,接下来脚本调用一个事务性COM对象的方法。一旦完成该页, COM+将通过检查是否有事务的某一部分调用了SetAbort方法来决定事务的结果。如果没有调用SetAbort方法,就触发OnTransactionCommit事件,并且提交该事务;如果调用了SetAbort方法,则触发OnTransactionAbort事件,回滚事务。
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50