标题:[转帖] ASP教程
只看楼主
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
   在上一篇中作者给大家详细介绍了两个非常实用的 ASP 内建对象 Application 和 Session 的使用方法。由于这两者的 OnStart、OnEnd 事件的脚本都必须在 Global.asa 文件中声明 , 因此,本篇将给大家详细介绍 Global.asa 文件的使用方法。为使大家熟练掌握至今所学过的知识,本篇还将举出一个 ASP 的 Chat 程序,供各位参考。    最近很多朋友来信问我,为什么前两期的范例程序运行时有这样那样的错。首先,我要向大家声明,这些程序都是我自己写的,在出“厂”前都经过合格检验,绝无“假冒伪劣产品”。:) 由于程序中使用了 cookie 记录客户信息,所以如果你在浏览器中没有设置接受 cookie 则程序将不能正常运行。另外,程序将客户信息记录在客户端的 cookie 所使用的方法是 Response.Cookie,此语句必须写在 ASP 文件中的第一个 < HTML> 标记前,这是因为 Cookie 是作为 HTTP 传输的头信息的一部分发送给客户的,如果当 HTTP 报头信息已经传输给客户后再使用 Response.Cookie,将出现以下错误 :“HTTP 标题已经写入到客户浏览器。任何 HTTP 标题的修改必须在写入页内容之前。”,可能一些朋友在剪贴程序的时候没有注意,打乱了程序的前后次序 , 或者是错误的将 HTML 代码添加在 ASP 范例程序之前,因而导致程序运行出错。因此,我建议大家一方面在首次运行例程的时候不要对程序进行任何改动,尽量在看懂程序的基础上逐步改进,另一方面在运行 ASP 程序时至少要在浏览器中选择可接受 Cookie,否则一旦 ASP 程序中使用了 Cookie 或 Session,它们都将无法正常运行。    下面我来向大家介绍 Global.asa 文件的使用方法。    什么是 Global.asa 文件?它其实是一个可选文件,程序编写者可以在该文件中指定事件脚本,并声明具有会话和应用程序作用域的对象。该文件的内容不是用来给用户显示的,而是用来存储事件信息和由应用程序全局使用的对象。该文件的名称必须是 Global.asa 且必须存放在应用程序的根目录中。每个应用程序只能有一个 Global.asa 文件。    在 Global.asa 文件中,如果包含的脚本没有用 < SCRIPT> 标记封装,或定义的对象没有会话或应用程序作用域,则服务器将返回错误。我们可以用任何支持脚本的语言编写 Global.asa 文件中包含的脚本。如果多个事件使用同一种脚本语言,就可以将它们组织在一组 < SCRIPT> 标记中。    在 Global.asa 文件中声明的过程只能从一个或多个与 Application_OnStart、Application_OnEnd、Session_OnStart 和 Session_OnEnd 事件相关的脚本中调用。在基于 ASP 的应用程序的 ASP 页中,它们是不可用的。如果要在应用程序之间共享过程,可在单独的文件中声明这些过程,然后使用服务器端包容 (SSI) 语句将该文件包含在调用该过程的 ASP 程序中。通常,包含文件的扩展名应为 .inc。    下面是一个很标准的 Global.asa 文件 : < SCRIPT LANGUAGE="VBScript" RUNAT="Server"> 'Session_OnStart 当客户首次运行 ASP 应用程序中的任何一个页面时运行 'Session_OnEnd 当一个客户的会话超时或退出应用程序时运行 'Application_OnStart 当任何客户首次访问该应用程序的首页时运行 'Application_OnEnd 当该站点的 WEB 服务器关闭时运行 < /SCRIPT> < SCRIPT LANGUAGE="VBScript" RUNAT="Server"> Sub Application_OnStart VisitorCountFilename = Server.MapPath ("/ex2") + "\VisitCount.txt" Set FileObject = Server.CreateObject("Scripting.FileSystemObject") Set Out= FileObject.OpenTextFile (VisitorCountFilename, 1, FALSE, FALSE) Application("visitors") = Out.ReadLine Application("VisitorCountFilename") = VisitorCountFilename End Sub '========================================================= SUB Application_OnEnd Set FileOutObject = Server.CreateObject("Scripting.FileSystemObject") Set Out= FileOutObject.CreateTextFile (Application("VisitorCountFilename"), TRUE,FALSE) Out.WriteLine(application("visitors")) End Sub '=========================================================Sub Session_OnStart Session.Timeout = 5 Application("visitors") = Application("visitors") + 1 Session("ID")=Session.SessionID End Sub < /SCRIPT>    在这个 Global.asa 程序中,涉及到了 ASP 的 File Access 组件,它可以提供用于访问文件系统的方法、属性和集合。这将在以后 ASP 的组件中进行展开讨论。在这里,它起到了在服务器上创建新文件并对文件进行写操作的作用。这其实是一个 ASP 页面访问记数器应用程序的 Global 文件,首先当客户首次访问该应用程序的首页时 , 过程 Application_OnStart 定义了在服务器上指定的虚拟目录下新建一个 VisitCount.txt 的文本文件,并将文件的路径和内容保存在应用程序级的变量中。而当任何一个客户访问 ASP 应用程序中的任何一个页面时,过程 Session_OnStart 定义将应用程序级的变量 visitors 的值自动加一。这样,每当有客户访问页面时,变量 visitors 都将自动加一,以起到统计点击率的作用。由于变量 visitors 的值是存储在系统内存之中,所以如果服务器关闭或重新启动,存储在变量中的数据将自动丢失,所以通过定义过程 Application_OnEnd,在服务器关闭或重启之前将数据写入事先建立的文本文件之中,这样就能确保当服务器再次启动时,Application_OnStart 过程可以从 VisitCount.txt 文件中读取以前的统计数。    经过这段时间的学习,相信大家已经能够比较熟练的运用我们所学过的这些 ASP 内建对象来编写一些较简单的 ASP 应用程序,可别小看你现在所掌握的这些 ASP 基本知识哦 ! 其实你已经能够开发一些简单但实用的 ASP 应用程序了。下面我就举一个非常简单的 ASP WEB 聊天室程序,你会发觉写聊天室原来是一件这么容易、轻松的事。可能朋友们已经在一些杂志上看到过 ASP 聊天程序的编写方法,但作者在这里自己写了一个更简单的程序,仅仅使用了一个 .asp 文件。请将以下代码剪贴到记事簿并保存为 chat.asp。 < %@ Language=VBScript %> < % Response.Buffer=true ' 设置输出缓存,用于显示不同页面。 On error resume next ' 忽略程序出错部分 If Request.ServerVariables("Request_Method")="GET" then ' 判断客户是以什么方式请求 WEB 页面 '------------------------ ' 客户登陆界面 '------------------------ %> < form method="POST" action="chat.asp">< p> < input type="text" name="nick" size="20" value="nick" style="background-color: rgb(192,192,192)">< br> < input type="submit" value=" 进入聊天室 " name="B1" style="color: rgb(255,255,0); font-size: 9pt; background-color: rgb(0,128,128)"> < p>< input type="hidden" name="log" size="20" value="1">< br>< /p> < /form> < % Response.End ' 结束程序的处理 Else Response.clear ' 清空缓存中的内容 dim talk If Request.Form("nick")<>"" then ' 判断客户是是否在聊天界面中 Session("nick")=Request.Form("nick") End If '------------------------' 客户聊天界面 '------------------------ %> < form method="POST" action="chat.asp" name=form1> < p>< %=Session("nick")%> 说话:< input type="text" name="talk" size="50">< br> < input type="submit" value=" 提交 " name="B1"> < input type="reset" value=" 取消 " name="B2">< /p> < /form> < A HREF="/asptest/shusheng/chat.asp"> 离开 < /a>< br>< br> < % If Request.Form("log")<>1 then If trim(Request.Form("talk"))="" then ' 判断用户是否没有输入任何内容 talk=Session("nick")&" 沉默是金。" Else talk=trim(Request.Form("talk")) ' 去掉字符后的空格 End If Application.lock Application("show")="< table border='0' cellpadding='0' cellspacing='0' width='85%' >< tr>< td width='100%' bgcolor='#C0C0C0'>< /td>< /tr>< tr>< td width='100%'>< font color='#0000FF'> 来自 "&Request.ServerVariables("remote_addr")&" 的 "&Session("nick")&time&" 说:< /font>"&talk&"< /td>< /tr>< tr>< td width='100%' bgcolor='#C0C0C0'>< /td>< /tr>< /table>< br>"&Application("show") Application.UnLock Response.Write Application("show") End If End If %>    第一次运行 chat.asp 程序,你首先将看到如下页面 :      选择你的 nick 进入聊天室后,将看到如下页面 :      输入你想要说的话,对话将出现在输入框的下方,如下图 :    下面我们来对这个聊天室程序进行逐步的分析。    首先,由于聊天室的所有客户都要能够共享信息,所以不可避免的要用到具有应用程序级变量的对象 Application,这是建立 Chat 程序的关键所在,所有的谈话数据都存放在一个应用程序级变量中,以便让所有的客户读取。我们可以用所学过的 request 对象获取客户所输入的谈话,并保存在变量 talk 中 , 然后将 talk 的值存入应用程序级变量 show 中,如下 :   < % Application("show")=talk&Application("show") %>    接下来要考虑的是当不同的客户同时向 Chat 应用程序进行操作的时候如何处理。这个问题其实与在数据库中的两个用户同时写入同一个记录一样,如果两个用户同时对同一个应用程序级变量进行写操作,则一个用户所作的修改会被另一个用户的操作所覆盖,所以,如果对 Application 对象数据的并发访问不采取一定措施,则会导致当两个用户试图同时对 Asp 聊天室应用程序提交时,一个用户的提交内容会被另一个用户的提交内容所覆盖,在被参加到会话中的任何人看到之前就消失了。为了避免这类问题的出现,我们需要使用 Application 对象的 Lock 属性来约束只允许当前的用户编辑或增加 Application 对象的属性,这样当用户开始修改应用程序级变量开始,到 Application 对象被显式地 Unlocked 为止,Application 对象的属性只能被该用户编辑,如果此时有其他用户请求编辑 Application 对象,则这些用户要排队等待,知道应用程序被 Unlock 为止。如下所示 : Application.lock Application("show")=talk&Application("show") Application.UnLock    现在整个程序的核心部分你已经了解了,下面考虑如何保存客户信息,这里我们要用到一个会话级变量,即将客户的 nick 保存在 Session 中。如: Session("nick")=Request.Form("nick")    最后,我们要考虑的是如何仅在一个 .asp 文件中处理各种事件 , 如 : 客户登陆界面、客户聊天界面。由于客户第一次请求 .asp 文件时,采用的是简单的 HTTP GET 方式,但是当客户向页面上的表单字段中增加的数据并向自身提交表单后,.asp 文件会再次被请求,不过这次数据是经过 HTTP POST 方式进行传递的。文件被请求的方式可以用两种方法来确定。一是测试 Request.Form 集合是否包含成员,若没有,则表明没有发送给表单处理的数据。二是使用 Request.ServerVariables("Request_Method") 变量。如果表单是通过 HTTP GET 方式被请求的,则这个变量会返回“GET”,如果表单被提交处理则返回“POST”。由于后一种方法对于确定文件的请求方式更直接,所以我们使用如下代码进行判断 :   if Request.ServerVariables("Request_Method")="GET" then    由于我们设置了 ASP 缓存,所以当程序判断页面请求方式为 GET 时,程序运行 Response.End,来结束后面的所有操作,否则则运行 Response.clear, 清空缓存中已有的内容,并继续程序的运行。这样我们就得以用同一个 .asp 文件根据不同情况给客户显示不同的界面。    好了,我已经将这个 ASP Chat 程序的核心部分告诉大家了,剩下的一些细节性问题请各位自己读程序吧,其实这个程序还存在很多不足之处,最大的毛病是我没有写自动刷新的功能,因此如果你在 Chat 中不说话,那也就看不到其他客户所说的话了。Chat 在 Internet 中的魅力大家是知道的,其实 , 用 ASP 也完全能做到同 irc 类似的强大功能,当然这就需要写更多的代码,如果大家有兴趣请写信给我,我将在今后的文章中逐步提升这个 chat 程序的等级,让大家也过过“Oper”的隐。注:有了这个 chat 程序,你就可以用来在自己的 PWS 上建一个 chat 应用程序,只要将你的 IP 地址告诉朋友,如 http://202.96.210.33/asp/chat.asp,你们就可以通过你的电脑在网上聊天了,很爽的,不信你试试 !

59ita点com(我就爱TA)
2005-09-19 23:44
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
   通过前九篇的理论和实践,相信大家已经对 ASP 有了系统的了解,虽然至今为止,我们只学了 ASP 的 4 个内建对象,但已经完全能够写出一些实用的小程序了。今天,作者将继续给大家讲解最后一个 ASP 内建对象——Server。    在开始本次课程之前,我仍要在这里回答一些朋友们提出的比较普遍的问题。最近仍有不少朋友来信问我,如何构建服务器端的 Active Server Page 环境。我想可能是我在前几篇中没有讲清楚,因此,在本篇的开头有必要把这个问题详细阐述一遍。    ASP 的应用完全是基于 Microsoft Internet Infomation Server(简称 IIS)之上的,IIS 有分别用于 Windows NT Server 和 WorkStation 的两个版本中(当然 IIS4.0 也有 Windows98 版,这里暂且不提),其功能几乎完全相同,所不同的只是安装过程。一般来说,我们使用的都是基于 NT 服务器上的 IIS 版本。在 NT Server 的环境中,发布信息、管理站点的工作一般都是通过 IIS 来完成的。通常我们在 NT4.0 版本中运行的是 IIS2.0 版,但它不具有支持 ASP 的功能。ASP 必须在安装完 IIS 后单独安装,安装文件是一个微软发布的 ASP 安装包,大约有 9 兆多,应该可以在微软的网站上下载。当 IIS2.0 中增添了支持 ASP 的功能后,其也就自动升级为 3.0 版本。2.0 和 3.0 对于 WEB 服务器来说,并没有什么大的改动,只是单纯地增加了运行 ASP 的能力。当安装完成后,运行 Internet 服务管理器,你将看到如下画面:    可以到在 IIS3.0 中提供了三种服务:WWW、Gopher、FTP,WWW 服务为客户浏览器提交 WEB 页,并允许客户访问 .asp 文件。当然,你可以直接安装最新的 IIS4.0 版本,作者也建议各位安装此版本,因为它具有更强更高的 WEB 管理机能和安全性。在 IIS4.0 中 IIS 的管理界面发生了根本性的改变,熟悉的 Internet 服务管理器,被取而代之为 Microsoft 管理控制台,简称 MMC。其界面如下图:    那么如何安装 IIS4.0 呢?在 NT4.0 上安装 IIS4.0 时,你的系统中必须已经安装了 NT SP3,以及 Internet Explorer4.01,注意这里的 Internet Explorer 的版本必须是 4.01,版本号为 4.72.3110.8。这点很重要,否则你将不能安装 IIS4.0。作者为了安装该版本特意花费了一个晚上在微软的站点上升级 IE 版本。    IIS 支持虚拟目录,通过在“服务器属性”对话框中的“目录”标签可以管理虚拟目录。建立虚拟目录对于管理 WEB 站点具有非常重要的意义。首先,虚拟目录隐藏了有关站点目录结构的重要信息。因为在浏览器中,客户通过选择“查看源代码”,很容易就能获取页面的文件路径信息,如果在 WEB 页中使用物理路径,将暴露有关站点目录的重要信息,这容易导致系统受到攻击。其次,只要两台机器具有相同的虚拟目录,你就可以在不对页面代码做任何改动的情况下,将 WEB 页面从一台机器上移到另一台机器。还有就是,当你将 WEB 页面放置于虚拟目录下后,你可以对目录设置不同的属性,如:Read、Excute、Script。读访问表示将目录内容从 IIS 传递到浏览器。而执行访问则可以使在该目录内执行可执行的文件。当你需要使用 ASP 时,就必须将你存放 .asp 文件的目录设置为“Excute(执行)”。作者建议大家在设置 WEB 站点时,将 HTML 文件同 ASP 文件分开放置在不同的目录下,然后将 HTML 子目录设置为“读”,将 ASP 子目录设置为“执行”,这不仅方便了对 WEB 的管理,而且最重要的提高了 ASP 程序的安全性,防止了程序内容被客户所访问。因为在今年 7 月底的时候 IIS 被一些网络高手发现了一个可怕的 bug,那就是,当你在一个站点的 .asp 文件后加上 ::$DATA 后,客户将能在浏览器中看到该 .asp 文件的所有源代码,这对于一个站点来说是非常可怕的。当然微软已经针对这个 bug,编写了补丁,但是为了彻底杜绝这种可能性的发生,作者还一建议大家不要将 .asp 所在的目录设置为可读。    我想,现在各位应该已经完全了解 ASP 的服务器端设置了,下面我们就进入正题 -- 学习 ASP 的最后一个内建对象 Server。    Server 对象提供对服务器上的方法和属性的访问 , 其中大多数方法和属性是作为实用程序的功能服务的。有了 Server 对象,你就可以在服务器上启动 ActiveX 对象例程,并使用 Active Server 服务提供象 HTML 和 URL 编码这样的函数。    一、语法    Server.property|method    二、属性    ScriptTimeout 超时值,在脚本运行超过这一时间之后即作超时处理。如下代码指定服务器处理脚本在 100 秒后超时。    < % Server.ScriptTimeout=100 %>    这里需要注意的是,通过使用元数据库中的 AspScriptTimeout 属性可以为 Web 服务或 Web 服务器设置缺省的 ScriptTimeout 值。ScriptTimeout 属性不能设置为小于在元数据库中指定的值。例如,如果 NumSeconds 设置为 60,而元数据库设置包含了默认值 90 秒,则脚本在 90 秒后超时。    三、方法    1、HTMLEncode 方法    HTMLEncode 方法允许你对特定的字符串进行 HTML 编码,虽然 HTML 可以显示大部分你写入 ASP 文件中的文本,但是当你需要实际包含 HTML 标记中所使用的字符,就会遇到问题。这是因为,当浏览器读到这样的字符串时,会试图进行解释。例如下面的这段文本 :    这是对 HTMLEncode 方法的测试。< br> 这里应该不会另起一行。    会被浏览器显示为 :    这是对 HTMLEncode 方法的测试。    这里应该不会另起一行。    为了避免此类问题,我们就需要使用 Server 对象的 HTMLEncode 方法,采用对应的不由浏览器解释的 HTML Character Code 替代 HTML 标记字符。所以,用下面的代码才能显示正确的 HTMLEncode 字符串,从而在浏览器中按你的需要输出文本。   < %   Response.write Server.HTMLEncode(" 这是对 HTMLEncode 方法的测试。< br> 这里应该不会另起一行。")%>    2、URLEncode 方法    就象 HTMLEncode 方法使客户可以将字符串翻译成可接受的 HTML 格式一样,Server 对象的 URLEncode 方法可以根据 URL 规则对字符串进行正确编码,当字符串数据以 URL 的形式传递到服务器时,在字符串中不允许出现空格,也不允许出现特殊字符。为此,如果你希望在发送字符串之前进行 URL 编码,可以使用 Server.URLEncode 方法。    3、MapPath 方法    MapPath 方法将指定的相对或虚拟路径映射到服务器上相应的物理目录上。    语法如下 :Server.MapPath(Path)    Path 指定要映射物理目录的相对或虚拟路径。若 Path 以一个正斜杠 (/) 或反斜杠 (\) 开始,则 MapPath 方法返回路径时将 Path 视为完整的虚拟路径。若 Path 不是以斜杠开始,则 MapPath 方法返回同 .asp 文件中已有的路径相对的路径。这里需要注意的是 MapPath 方法不检查返回的路径是否正确或在服务器上是否存在。    对于下列示例,文件 data.txt 和包含下列脚本的 test.asp 文件都位于目录 C:\Inetpub\Wwwroot\asp 下。C:\Inetpub\Wwwroot 目录被设置为服务器的宿主目录。下列示例使用服务器变量 PATH_INFO 映射当前文件的物理路径。以下脚本    < %= server.mappath(Request.ServerVariables("PATH_INFO"))%>    输出    c:\inetpub\wwwroot\asp\test.asp    由于下列示例中的路径参数不是以斜杠字符开始的,所以它们被相对映射到当前目录,此处是目录 C:\Inetpub\Wwwroot\asp。以下脚本   < %= server.mappath("data.txt")%>   < %= server.mappath("asp/data.txt")%>    输出 c:\inetpub\wwwroot\asp\data.txt c:\inetpub\wwwroot\asp\asp\data.txt    4、CreateObject 方法    Server.CreateObject 恐怕是 ASP 中最为实用,也是最强劲的功能了。它用于创建已经注册到服务器上的 ActiveX 组件实例。这是一个非常重要的特性,因为通过使用 ActiveX 组件能够使你轻松地扩展 ActiveX 的能力,正是使用了 ActiveX 组件,你可以实现至关重要的功能,譬如数据库连接、文件访问、广告显示和其他 VBScript 不能提供或不能简单地依靠单独使用 ActiveX 所能完成的功能。正是因为这些组件才使得 ASP 具有了强大的生命力。    其语法如下:    Server.CreateObject("Component Name")    默认情况下,由 Server.CreateObject 方法创建的对象具有页作用域。这就是说,再当前 ASP 页处理完成之后,服务器将自动破坏这些对象。如果要创建有会话或应用程序作用域的对象,可以使用 < OBJECT> 标记并设置 SESSION 或 APPLICATION 的 SCOPE 属性,也可以在对话及应用程序变量中存储该对象。如下例程 :    < % Set Session("ad") = Server.CreateObject("MSWC.AdRotator")%>    这里需要注意的是,不能创建与内建对象同名的对象实例,否则,如下列脚本将返回错误。    < % Set Response = Server.CreateObject("Response") %>    至今为止,我们已经学习完了 ASP 所有的内建对象,不知大家是不是很兴奋?其实 ASP 是很简单的,只要大家不断的实践,相信一段时间后都不难成为 ASP 的高手。从下一篇起作者将开始介绍 ASP 内建 ActiveX 组件,这也是 ASP 运用中非常重要和实用的一部分。敬请关注。

59ita点com(我就爱TA)
2005-09-19 23:46
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
  原定计划从本篇开始就要给大家介绍 ASP 内建的 ActiveX 组件,但是考虑到我们在往后的学习中将会接触到大量的数据库查询,因此作者临时决定花一到两篇的篇幅向大家简要介绍一些数据库查询语言的基本知识,这其实也是学习 ASP 所必须掌握的一门知识。是否能够灵活地运用数据库查询语言,将直接关系到 ASP 程序的执行效率等一系列问题,所以请各位务必重视。
   
     相信很多朋友都听说过 SQL 这个名字,如果你是计算机方面的行家,SQL 的大名一定是如雷贯耳。那么 SQL 究竟是什么呢?SQL 一词实际上是 "Structured Query Language" 结构式查询语言的缩写,是用于对存放在计算机数据库中的数据进行组织、管理和检索的一种工具;是一种特定类型的数据库 -- 关系数据库。而控制这种数据库的计算机程序就是我们常说的 DBMS-- 数据库管理系统。譬如:SQL Server、Oracle、Sybase、DB2 等等。当用户想要检索数据库中的数据时,就通过 SQL 语言发出请求,接着 DBMS 对该 SQL 请求进行处理并检索所要求的数据,最后将其返回给用户,此过程被称作为数据库查询,这也就是数据库查询语言这一名称的由来。
   
     SQL 并不是象 C、COBOL 和 Fortran 语言那样的完整的计算机语言。SQL 没有用于条件测试的 IF 语句,也没有用于程序分支的 Goto 语句以及循环语句 For 或 Do。确切的讲,SQL 是一种数据库子语言,SQL 语句可以被嵌入到另一种语言中,从而使其具有数据库存取功能。SQL 也非严格的结构式语言,它的句法更接近英语语句,因此易于理解,大多数 SQL 语句都是直述其意,读起来就象自然语言一样明了。SQL 还是一种交互式查询语言,允许用户直接查询存储数据,利用这一交互特性,用户可以在很短的时间内回答相当复杂的问题,而同样问题若让程序员编写相应的报表程序则可能要用几个星期甚至更长时间。
   
     在大部分 ASP 应用程序中我们都会接触到数据库,而我们在编写 ASP 应用程序时用来进行数据库操作的标准语法正是 SQL,因此 SQL 语法的重要性是不言而喻的。下面,我们就从最常用的 SQL 语句 SELECT 着手,一步一步地来学习 SQL。
   
     查询是 SQL 语言的核心,而用于表达 SQL 查询的 SELECT 语句则是功能最强也是最为复杂的 SQL 语句,它从数据库中检索数据,并将查询结果提供给用户。在本文中我们将建立一个名为 tianjiao 的简单数据库,该库中存放了一个叫 sales 的销售记录表,如下所示 :
   
  姓名 性别 工资 销售目标 销售额 地区
  书生 男 2500 8000 9000 上海
  吴冠军 男 3000 10000 9999 北京
  雷鸣 男 2000 8000 10000 四川
  雪儿 女 2500 5000 6000 广州
  顾一 男 2600 9000 9800 大连
  阿卓 女 2000 4000 4000 天津
  熠天 男 4000 20000 20000 全国
   
   
     在该表中有六列即六个字段 : 姓名、性别、工资、销售目标、销售额、地区,首先我们用 Select 语句列出姓名、销售目标和销售额 :
   
     Select 姓名,销售目标,销售额 From sales
   
     结果如下 :
   
  姓名 销售目标 销售额
  书生 8000 9000
  吴冠军 10000 9999
  雷鸣 8000 10000
  雪儿 5000 6000
  顾一 9000 9800
  阿卓 4000 4000
  熠天 20000 20000
   
   
     然后,我们再列出所有男性的姓名、销售目标和销售额 :
   
     Select 姓名,销售目标,销售额 From sales Where 性别 =" 男 "
   
     结果如下 :
   
  姓名 销售目标 销售额
  书生 8000 9000
  吴冠军 10000 9999
  雷鸣 8000 10000
  顾一 9000 9800
  熠天 20000 20000
   
   
     接下来,我们做一个相对复杂的查询,列出销售额大于销售目标的所有男性的姓名、销售目标和销售额,并且按销售目标排序。
    Select 姓名,销售目标,销售额
    Form sales
    Where 销售额 &gt; 销售目标
    And 性别 =" 男 "
    Order By 销售目标
   
     结果如下 :
   
  姓名 销售目标 销售额
  书生 8000 9000
  雷鸣 8000 10000
  顾一 9000 9800
  熠天 20000 20000
   
   
     大家可以看到,对于简单查询,SQL Select 语句和英文语法很相象,我们来分析一下 SELECT 语句的完整格式,它包括六个子句,其中 SELECT 和 FROM 子句是必须的,其它子句可以任选,每个子句的功能如下 :
   
     1、Select 子句列出所有要求 SELECT 语句检索的数据项。它放在 SELECT 语句开始处,指定此查询要检索的数据项。这些数据项通常用选择表表示,即一组用“,”隔开的选择项。按照从左到右的顺序,每个选择项产生的一个列的查询结果,一个选择项可能是以下项目:
   
     (1)、列名:标识 FROM 子句指定表中的列。如果列名作为选择项,则 SQL 直接从数据库表中每行取出该列的值,再将其放在查询结果的相应行中。
     (2)、常数:指定在查询结果的每行中都放上该值。
   
     (3)、SQL 表达式:说明必须将要放入查询结果中的值按表达式的规定进行计算。
   
     2、From 子句列出包含所要查询数据的表,它由关键字 FROM 后跟一组用逗号分开的表名组成。每个表明都代表一个包括该查询要检索数据的表。这些表称为此 SQL 语句的表源,因为查询结果都源于它们。
     3、Where 子句告诉 SQL 只查询某些行中的数据,这些行用搜索条件描述。
   
     4、Group By 子句指定汇总查询,即不是对每行产生一个查询结果,而是将相似的行进行分组,再对每组产生一个汇总结果。
   
     5、Having 子句告诉 SQL 只产生有 Group By 得到的某些组的结果,和 Where 子句一样,所需要的组也用一个搜索条件指定。
   
     6、Order By 子句将查询结果按一列或多列中的数据排序。如果省略此子句,则查询结果将是无序的。
   
     下面作者将提供一个简单但实用的运用 SQL 语句查询的 ASP 程序供大家参考。
   
     为了使大家更清楚更直接地了解 SQL 语法在 ASP 中的应用,我们先将查询的所有核心过程写成一个名为 query2table 的 SUB,然后利用 ASP 的服务器端包容功能调用该 SUB。请将以下语句剪贴到记事簿,保存为 subdbtable.inc 文件,并置于虚拟目录 asptest 下 :
    &lt; %
    sub query2table(inputquery)
    set conntemp=server.createobject("adodb.connection")
    conntemp.open "DSN=Student;uid=student;pwd=aspmagic"
    set rstemp=conntemp.execute(inputquery)
    howmanyfields=rstemp.fields.count -1
    ' 统计数据库中的列数
    %&gt;
    &lt; table border=1&gt;&lt; tr&gt;
    &lt; %
    for i=0 to howmanyfields
    %&gt;
    &lt; td&gt;&lt; b&gt;&lt; %=rstemp(i).name%&gt;&lt; /B&gt;&lt; /TD&gt;
    &lt; % next %&gt;
    &lt; /tr&gt;
    &lt; %
    do while not rstemp.eof
    %&gt;
    &lt; tr&gt;
    &lt; % for i = 0 to howmanyfields
    thisvalue=rstemp(i)
    If isnull(thisvalue) then
    thisvalue="?
    ' 如果字段为空,则将变量 thisvalue 的值定义为一个空格
    end if%&gt;
    &lt; td valign=top&gt;&lt; %=thisvalue%&gt;&lt; /td&gt;
    &lt; % next %&gt;
    &lt; /tr&gt;
    &lt; %rstemp.movenext
    loop%&gt;
    &lt; /table&gt;
    &lt; %
    rstemp.close
    set rstemp=nothing
    conntemp.close
    set conntemp=nothingend sub%&gt;
   
     完成了 SUB 的定义过程,在下面几个 ASP 程序中我们只要加入想要使用的 SQL 查询语句,并调用该过程就可以非常方便的得到查询结果。将以下四段代码分别保存为 asp11a.asp、asp11b.asp、asp11c.asp、asp11d.asp 四个 .asp 文件。
   
    &lt; HEAD&gt;&lt; TITLE&gt;asp11a.asp&lt; /TITLE&gt;&lt; /HEAD&gt;
    &lt; HTML&gt;&lt; body bgcolor="#FFFFFF"&gt;
    &lt; %
    call query2table("select * from publishers where name like 'A%%'")
  ' 将表 publishers 中所有姓名中有字母 A 的记录查询出来
    %&gt;
    &lt; !--#include virtual="/asptest/subdbtable.inc"--&gt;&lt; /BODY&gt;&lt; /HTML&gt;
   
   
    &lt; HEAD&gt;&lt; TITLE&gt;asp11b.asp&lt; /TITLE&gt;&lt; /HEAD&gt;&lt; HTML&gt;&lt; body bgcolor="#FFFFFF"&gt;
    &lt; %
    call query2table("select * from titles where Year_Published &gt; = 1998")
  ' 将表 titles 中所有发表年份大于或等于 1998 年的记录查询出来
    %&gt;
    &lt; !--#include virtual="/asptest/subdbtable.inc"--&gt;&lt; /BODY&gt;&lt; /HTML&gt;
   
   
    &lt; HEAD&gt;&lt; TITLE&gt;asp11c.asp&lt; /TITLE&gt;&lt; /HEAD&gt;&lt; HTML&gt;&lt; body bgcolor="#FFFFFF"&gt;
    &lt; %
    call query2table("select * from publishers where amount&gt;10000 and sex='male'")
  ' 将表 publishers 中所有数量大于 10000 且性别为男的记录查询出来
    %&gt;
    &lt; !--#include virtual="/asptest/subdbtable.inc"--&gt;&lt; /BODY&gt;&lt; /HTML&gt;
   
   
    &lt; HEAD&gt;&lt; TITLE&gt;asp11d.asp&lt; /TITLE&gt;&lt; /HEAD&gt;&lt; HTML&gt;&lt; body bgcolor="#FFFFFF"&gt;
    &lt; %
    call query2table("select * from publishers where state&lt; &gt; 'NY'")
  '将表 publishers 中所有所在城市不为纽约的记录查询出来。
    %&gt;
    &lt; !--#include virtual="/asptest/subdbtable.inc"--&gt;&lt; /BODY&gt;&lt; /HTML&gt;
   
     利用 subdbtable.inc 文件中的所定义的过程 query2table,你就可以非常迅速地对数据库进行查询,你所要做的只是将“conntemp.open "DSN=Student;uid=student;pwd=aspmagic"”中的数据库名称、用户身份和密码稍加改动,并在调用 query2table 时输入想要使用的 SQL 查询语句即可。是不是很简单 ? 这就是 ASP 和 SQL 的魅力所在 !!!
   
     今天,我们虽然用了一整篇的篇幅只学习了一个 SQL 指令,但请你相信你所获得远不同于一个 DOS 指令,SELECT 指令使得你可以非常容易地对数据库进行查询,或许在这之前你对数据库查询还一无所知,但是通过本篇的学习,你其实已经会使用 ASP 进行常用的数据库查询了,是不是很激动 ? 在下一篇中,作者将继续给大家介绍 SQL 的其它几个基本指令。在结束本文之前,作者在这里要向很多来信的朋友致歉,由于最近作者工作繁忙,实在无暇一一回答各位的问题,请见谅,我会尽量将一些常见的、发生频率较高的问题在文章中写出来,至于一些不常见的问题,我建议大家到下面这个站点提问,你将会得到及时的答复。www., 这是作者至今为止所见的最棒的中文 ASP 学习站点,由上海的飞鸟主持,大家务必去看看。
   

59ita点com(我就爱TA)
2005-09-19 23:47
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
   在本篇的开头,我要感谢一些朋友来信给我指出了前几篇文章中的错误。不知大家是否记得在第八篇中我举了一个简单的利用 Application 制作的页面访问计数器?有位朋友来信问我,为何当他改变计数器起始变量 NumVisits 的值后对最后的记数结果没有任何作用?起初我也大惑不解,让我们来回忆一下这段源程序,如下:
  &lt; %
  Dim NumVisits
  NumVisits=0
  Application.Lock
  Application("NumVisits") = Application("NumVisits") + 1
  Application.Unlock
  %&gt;
  欢迎光临本网页,你是本页的第 &lt; %= Application("NumVisits") %&gt; 位访客 !    在这段程序中,如果你试图通过改变变量 NumVisits 的值来改变记数器结果,是绝对办不到的。因为用变量的值去改变 Application 的值是不可以的,这两者是不相关的。所以这里对变量的定义和赋值都是多余的。那么我们究竟应该如何来给 Application("NumVisits") 定义一个初始值呢?请看以下修正后程序:
  &lt; %
  If Application("NumVisits")&lt; 999 then
  Application("NumVisits")=999
  End If
  Application.Lock
  Application("NumVisits")=Application("NumVisits")+1
  Application.Unlock
  %&gt;
  欢迎光临本网页,你是本页的第 &lt; %= Application("NumVisits") %&gt; 位访客 !
   
     这里的 999 就是你要设定的计数器初始值,如此一来问题就迎刃而解了。我非常感谢这位姓康的朋友给我指出了这个错误,虽然这只是一个很小的漏洞,但我们在共同学程序写程序的过程中非常需要这种严谨细致的作风,希望今后朋友们们一旦发现文中的错误即刻来信告知,我也能及时纠正,谢谢。
   
     SQL 语言可以分为两大部分:数据定义语言和数据操纵语言,继上一篇我们学习了数据操纵语言中的 Select 语句后,今天作者要继续给大家简要介绍其余的 SQL 语句。
   
     SQL 是一种完备的数据处理语言,不仅用于数据库查询,而且用于数据库中的数据修改和更新,与支持 SQL 查询的 Select 语句的复杂性相比较,更改数据库内容的 SQL 语句就格外简单。然而对于一个 DBMS 来说,数据更新所造成的风险大大超出了数据查询。数据库管理系统必须在更改期内保护所存储的数据的一致性,确保有效的数据进入数据库,数据库必须保持一致性, DBMS 还必须协调多用户的并行更新,以确保用户和他们的更改不至于影响其他用户的作业。
     用于修改数据库内容的 SQL 语句主要有以下三个:
   
     1、 Insert,向一个表中加入新的数据行
   
     2、 Delete,从一个表中删除数据行
   
     3、 Update,更改数据库中已经存在的数据
   
     首先我们来看看 Insert 的用法:
   
     标准语法:
     INSERT INTO table_name
     (col1, col2...)
     VALUES(value1, value2...)
   
     下例要将书生作为一个新的销售员加入表 Salesreps 中
     Insert Into
     Salesreps (name,num,sales,hire_date,income)
     values ('shusheng',9,10000,'23-Feb-99',2000)
   
     在此语句中,列的名称列在括号中以逗号隔开,接下去是 Value 短语和括号中同样以逗号隔开的每列数据,应该注意的是数据和列名称的顺序是相同的,而且若是字符串型则以单引号隔开。从概念上来讲, Insert 语句建立的一个与表列结构相一致的数据行,用取自 Values 子句的数据来填充它,然后将该新行加入表中,表中的行是不排序的,因此不存在将该行插入到表的头或尾或两行之间的这个概念。 Insert 语句结束后,新行就是表的一部分了。
   
     Insert 语句还可以将多行数据添加到目标表中去,在这种形式的 Insert 语句中,新行的数据值不是在语句正文中明确地指定的,而是语句中指定的一个数据库查询。添加的值来自数据库自身的行,这乍看起来似乎有些奇怪,但是在某些特定的状态下,这是非常有用的。比如,你想把 1998 年 12 月 30 日之前产生的订单编号、日期和数目从 order 表中拷贝到另一个名为 oldorder 的表中去,多行 Insert 语句为拷贝数据提供了一种紧凑而高效的方法,如下:
     Insert into oldorder (Num,Date,Amount)
     Select Num,Date,Amount
     From order
     Where Date&lt;'30-12-98'
   
     这条语句看起来有些复杂,其实很简单,语句标识了接收新行的表 oldorder 和接收数据的列,完全类似于单行 Insert 语句。语句的剩余部分是一个查询,它检索 order 表中的数据。 SQL 先执行对 order 表的查询,然后将查询结果逐行插入到 oldorder 表中去。
   
     下面我们来看看 Update 的用法, Update 语句用于更新单表中选定行的一列或多列的值。要更新的目标表在语句中定义, Set 子句则指定要更新哪些列并计算他们的值。 Update 语句总是包含 Where 语句,而且 Update 语句比较危险,所以您必须明确地认识到 Where 语句的重要性, Where 语句被用来指定需要更新的行。
     标准语法:
     UPDATE table_name
     SET columnname1 = value1
     [, columname2 = value2]...
     WHERE search_condition
   
   
     以下是一个简单的 Update 语句的例子 :
     Update customers
     Set credit=100000.00,id=99
     Where name='asp'
   
   
     在此例中我们将表 customers 中客户名为 asp 的客户的信贷值更新为 10 万并将他的 ID 变更为 99。再看下例:
     Update customers
     Set credit=200000.00,state=021
     Where ID in (80,90,100,120)
   
   
     我们可以发现,其实 SQL 处理 Update 语句的过程就是逐行遍历所指定的表,更新其搜索条件结果为“真”的行,跳过其搜索条件结果为“假”或“空”的行。
   
     最后,来看看 Delete 语句。
   
     标准语法:
     DELETE FROM tablename
     WHERE condition
   
   
     由于它过于简单,所以所造成的后果也是严重的,虽然其中的 Where 子句是任选的,但它几乎总是存在的,若将 Where 子句从 Delete 语句中省略掉,则目标表的所有行都将被删除。看下例:
     Delete from order Where ID=99
   
     在文章的末尾,作者在给大家简要介绍一下数据定义语言。它是用来创建和修改数据库结构的一种语句,包括 Create 和 Drop 语句。
   
     1、 Create 语句
   
     标准语法:
     CREATE TABLE table_name
     ( field1 datatype [ NOT NULL ],
     field2 datatype [ NOT NULL ],
     field3 datatype [ NOT NULL ]...)
   
     如:
     CREATE TABLE BILLS
     ( NAME CHAR(30),
     AMOUNT NUMBER,
     ACCOUNT_ID NUMBER)
   
     尽管 Create Table 比前面介绍的语句难理解一些,但仍然很直观。它将 bills 赋予一个新表,并指定表中三列的名称和数据类型。表被建立后我们就可以添入数据了。如:
   
     Insert into bills(name,amout,account_id) values('gates',100,1)
   
     如果,你觉得不再需要保存产品信息,则可用 Drop table 语句将该表及其所包含的所有数据从数据库中删除掉。
   
     标准语法:
   
     DROP TABLE table_name
   
     至此,我们已经了解了所有常用的 SQL 语句,可别小看这些貌似英文的简单语句,它们的功能十分强大,当我们编写 asp 程序时必须使用他们对数据库进行操作。从下一篇开始,作者将给大家介绍 ASP 的内建 ActiveX 组件,敬请关注。
   

59ita点com(我就爱TA)
2005-09-19 23:48
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
     当你用 ASP 编写服务器端应用程序时,必须依靠 ActiveX 组件来强大 Web 应用程序的功能,譬如:你需要连接数据库,对数据库进行在线操作等等,本文从本篇开始将陆续给大家介绍 ASP ActiveX 组件的使用方法。
   
     从今天开始我们将正式学习 ASP 的精华部分 --ActiveX 组件。事实上,当你用 ASP 编写服务器端应用程序时,必须依靠 ActiveX 组件来强大 Web 应用程序的功能,譬如:你需要连接数据库,对数据库进行在线操作或者对 WEB 服务器上的文件系统进行操作,亦或你需要一个 WEB 广告交换程序,所有这一切你都必须通过调用 ASP 内建的 ActiveX 组件或自己编写所需的组件来完成。
   
     那么,究竟什么是 ActiveX 组件呢?它又是如何运作的呢?其实 ActiveX 组件是一个存在于 WEB 服务器上的文件,该文件包含执行某项或一组任务的代码,组件可以执行公用任务,这样就不必自己去创建执行这些任务的代码。例如,股票行情收报机组件可以在 Web 页上显示最新的股票报价。当你在 WEB 服务器上安装完 ASP 环境后,就可以直接使用它自带的几个常用组件,如 Database Access 组件。当然你也可以从第三方开发者处获得可选的组件 , 也可以编写自己的组件。你可以利用组件作为脚本和基于 Web 应用程序的基本构造块,只要知道如何访问组件提供的对象,即使你是位编写脚本的新手,也可以在不了解组件运作方式的情况下编写 ASP 程序。总而言之, ActiveX 组件使您不用学习复杂的编程就能够写出强大的 WEB 服务器端脚本。如果您是位 Web 应用程序的开发者,可以使用任何支持组件对象模型(COM)的语言来编写组件,如, C、 C++、 Java 或 Visual Basic。如果你熟悉 COM 编程, ActiveX 组件就是 Automation 服务器。但是要在 Web 服务器上运行, ActiveX 组件不能有图形用户接口元素,如 Visual Basic 的 MsgBox 函数。组件是可以重复使用的。在 Web 服务器上安装了组件后,就可以从 ASP 脚本、 ISAPI 应用程序、服务器上的其他组件或由另一种 COM 兼容语言编写的程序中调用该组件。
   
     那么我们在 ASP 中应该如何调用组件呢?如前所述,组件是包含在动态链接库 (.dll) 或可执行文件 (.exe) 中的可执行代码。组件可以提供一个或多个对象以及对象的方法和属性。要使用组件提供的对象,我们首先要创建对象的实例并将这个新的实例分配变量名。使用 ASP 的 Server.CreateObject 方法可以创建对象的实例。接着,使用脚本语言的变量分配指令为对象实例命名。创建对象实例时,必须提供实例的注册名称“PROGID”。如下要创建一个 Ad Rotator 对象的实例 :
     &lt; % Set MyAds = Server.CreateObject("MSWC.AdRotator") %&gt;
   
     我们必须使用 ASP 的 Server.CreateObject 方法来创建对象实例,否者 ASP 无法跟踪脚本语言中对象的使用。
   
     使用 HTML&lt; OBJECT&gt; 标签同样可以创建对象实例,但必须为 RUNAT 属性提供服务器值,同时也要为将在脚本语言中使用的变量名提供 ID 属性组。使用注册名 (PROGID) 或注册号码 (CLSID) 可以识别该对象。下面的例子使用注册名 (PROGID) 创建 Ad Rotator 对象的实例:
     &lt; OBJECT RUNAT=Server ID=MyAd PROGID="MSWC.AdRotator"&gt;&lt; /OBJECT&gt;
   
     下面列出了 ASP 可安装的常用组件。
   
  Ad Rotator 创建一个 AdRotator 对象,该对象可按指定计划在同一页上自动轮换显示广告。
  Browser Capabilities 创建一个 BrowserType 对象,该对象决定访问 Web 站点的每个浏览器的性能、类型及版本。
  Database Access 提供用 ActiveX Data Objects (ADO) 对数据库的访问。
  Content Linking 创建一个 NextLink 对象,该对象可生成 Web 页内容列表,并象书一样将各页顺续连接。
  File Access 组件 提供文件的输入输出访问。
  Collaboration Data Objects for NTS 组件 可以快速、简便的在 Web 页上添加收发邮件功能。该组件只适用于 Internet Information Server for Windows NT? Server 。
  MyInfo 创建一个 MyInfo 对象,该对象追踪个人信息,例如站点管理员的姓名、地址及显示选择。
  Counters 创建一个 Counters 对象,该对象可以创建、保存、增加或检索任意数量的独立计数器。
  Content Rotator 自动翻转 Web 主页上的 HTML 内容字符串。
  Page Counter 记录并显示 Web 页被打开的次数。
   
     现在 WEB 广告几乎充斥了整个网络,那么究竟如何在你自己的网站上建立一个符合广告领域标准功能的广告系统呢?答案是利用 ASP AD Rotator 组件 ! 它允许在每次访问 ASP 页面时在页面上显示新的广告,并且提供了很强的功能,例如 : 旋转显示在页面上的广告图象的能力、跟踪特定广告显示次数的能力以及跟踪客户端在广告上单击次数的能力。 AD Rotator 组件的工作是通过读取 AD Rotator 计划文件来完成的,该文件包括与要显示的图象文件的地点有关的信息以及每个图象的不同属性,下面就是一个标准的 AD Rotator 计划文件 :
  ---ADROT.TXT---
  REDIRECT /scripts/adredir.asp
  WIDTH 440
  HEIGHT 60
  BORDER 1
  *
  ads/homepage/chinabyte.gif
  http://www.
  Check out the IT site
  2
  ads/homepage/gamichlg.gif
  -
  Sponsored by Flyteworks
  3
  ads/homepage/asp.gif
  http:// www.
  Good ASP site on net
  3
  ads/homepage/spranklg.gif
  http://www.
  The #1 Sports site on the net
  2
   
     该段代码的前四行包含广告的全局设置。 Redirect 行指出广告将成为其热连接的 URL, 注意这里不是为广告本身指定的 URL,而是将调用的中间页面的 URL,这样我们就可以通过这个中间页面跟踪单击广告的次数。该 Redirect URL 将与包含两个参数的查询字符串一起调用 : 特定广告主页的 URL 和图象文件的 URL。星号上面的其余三行简单说明如何显示广告。前两行以像素为单位指定网页上广告的宽度和高度,默认值是 440 和 60 个像素。后一行,同样是以像素为单位指定广告四周超链接的边框宽度 , 默认值是 1 个像素。如果将该参数设置为 0,则将没有边框。
   
     星号下面的行以每四行为一个单位描述每个广告的细节。在此例中共有 16 行,描述四个广告。每个广告的描述包含图象文件的 URL、广告的主页 URL(如果广告客户没有主页,请在该行写上一个连字符“-”,指出该广告没有链接)和图象的替代文字以及指定该页与其他页交替显示频率的数值。
   
     图象是重定向页面的热连接,它在查询字符串中设置了两个值, url=/scripts/adredir.asp 以及 image=/ads/homepage/asp.gif。要确定广告显示的频率,可以将计划文件中所有广告的权值相加,在该例中总数是 10,那么 aspallian 的广告权值为 3,这意味着 AdRotator 组件每调用十次,它则显示 3 次。
   
     重定向文件是用户创建的文件。它通常包含用来解析由 AdRotator 对象发送的查询字符串的脚本并将用户重定向到与用户所单击的广告所相关的 URL。用户也可以将脚本包含进重定向文件中,以便统计单击某一特定广告的用户的数目并将这一信息保存到服务器上的某一文件中。增加计数器和重定向用户是通过下面两行 ASP 脚本来实现的 :
  &lt; %
  Counter.Increment(request.querystring("url"))
  response.redirect(request.querystring("url"))
  %&gt;
   
     现在我们看一下 Ad Rotator 组件是如何在页面中使用的,首先必须使用 Server.CreateObject 方法实例化 Ad Rotator 对象。 Ad Rotator 组件的 PROGID 属性是 MSWC.AdRotator。完整的代码如下 :
  &lt; % Set ad = Server.CreateObject("MSWC.AdRotator") %&gt;
  &lt; %= ad.GetAdvertisement("/ads/adrot.txt") %&gt;
   
   
     Ad Rotator 组件支持的唯一方法是 GetAdvertisement,它只有一个参数 :AdRotator 计划文件的名称。注意指向文件的路径是从当前虚拟目录的相对路径,物理路径是不允许的。 GetAdvertisement 方法从 Rotator 计划文件中获取下一个计划广告的详细说明并将其格式化为 HTML 格式。下面的 HTML 由 GetAdvertisement 方法生成且被添加到网页的输出中,以便显示 Rotator 计划文件中的下一个广告。
  &lt; A HREF="http://www. IMG
  SRC="http://www. ALT="Good ASP site on net" WIDTH=440 HEIGHT=60 BORDER=1&gt;&lt; /A&gt;
   
     使用 AdRotator 组件我们可以直接通过对象属性而不是计划文件中的设置来直接控制某些广告特性,其可用属性如下 :
   
     Border 指定广告边框的大小。
   
     Clickable 指定广告是否为超链接。
   
     TargetFrame 指定显示广告的框架的名称。
  &lt; %
  Set ad = Server.CreateObject("MSWC.AdRotator")
  ad.Border = 0
  ad.Clickable = true
  ad.TargetFrame = AdFrame
  ad.GetAdvertisement("/ads/adrot.txt")
  %&gt;
   
     通过上面的学习,相信你已经能够熟练运用 ASP 的内建 AdRotator 组件为自己的网站建立一个标准的广告显示程序了。你是否难以相信一切竟是如此的简单?其实真正能令你震惊的还在后头呢,敬请关注下一篇 ASP ActiveX 组件大揭密!

59ita点com(我就爱TA)
2005-09-19 23:49
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
  当你用 ASP 编写服务器端应用程序时,必须依靠 ActiveX 组件来强大 Web 应用程序的功能,譬如:你需要连接数据库,对数据库进行在线操作等等,继上篇介绍了 AD Rotator 组件后,本篇将接着给大家介绍其它一些常用的 ASP ActiveX 组件的使用方法。   最近仍有不少朋友来信问我, ASP 是否只能在 Microsoft IIS 上运行,是否可以在非 NT 平台上运作?本来这个问题我已经回答过很多遍了 : 我只是听说过有某种可以支持的软件,却从没见过。但一些热情的朋友仍然孜孜不倦地来信询问,于是在朋友们的盛情之下,我访遍了 ASP 相关站点,竟惊奇的发现,原来 ASP 的确是可以运行在其它非 NT 平台上的,因此在本篇的开头,我就给来信的朋友们简要介绍一下如何在非 NT 平台上使用 ASP。   要在非 NT 平台上开发并运行 ASP 应用程序我们可以依赖于一套名为 Instant ASP 的第三方软件,它的广告标语非常吸引人“ASP Anytime, Anywhere”,我想所有 ASP 的开发者们看到如此的标语必然兴奋不已。这套由 Halcyon 软件公司开发的软件使得你无需重复开发原有 ASP 应用程序即可以将它运行在任何操作平台上 ! 这样非但节省了大量的开发时间,而且使得 ASP 真正成为了一种跨平台的 Internet、 Intranet 或 Extranet 应用程序。 Instant ASP 本身其实是一套基于 Java 的应用程序,因此通过它你可以将基于 WEB 的 ASP 应用程序运行在任何平台上,下表列出了 Instant ASP 目前版本所支持的操作平台。   更令人吃惊的是 Instant ASP 不仅提供了 ASP 的运作环境,而且它较目前市场上的 ASP 应用还提供了更为强大和实用的功能,它将 ActiveX 组件和 Enterprise Java Beans 或者 CORBA-compliant objects 组合起来,从而使 ASP 有了更为广泛的应用。它同样提供了通过 ADO 接口访问连接各种数据库,并生成动态页面的强大功能。对于开发者而言可以使用自己擅长的编程语言或工具如 :Visual Basic, JScript, VBScript, C++, Java, HTML, Delphi , MS Visual InterDev 等等来进行开发。关于 Instant ASP 具体安装和操作我就不在这里展开了,有兴趣的朋友可以到它的站点上去看看 halcyonsoft.com,你还可以免费下载一个试用版试试。   继上一篇中作者给大家介绍了 AD Rotator 组件的使用方法后,今天我们接着来看看其它的一些 ASP 常用组件。    一、 Database Access 组件   我们在 WEB 服务器上运用 WEB 应用程序进行的最常见和最实用的任务就是访问服务器端的数据库。而 ASP 内建的 Database Access 组件使得我们能够轻而易举地通过 ActiveX Data Objects (ADO) 访问存储在服务器端的数据库或其他表格化数据结构中的信息。 ADO 是对当前微软所支持的数据库进行操作的最有效和最简单直接的方法,它是一种功能强大的数据访问编程模式,从而使得大部分数据源可编程的属性得以直接扩展到你的 Active Server 页面上。可以使用 ADO 去编写紧凑简明的脚本以便连接到 Open Database Connectivity (ODBC) 兼容的数据库和 OLE DB 兼容的数据源,这样 ASP 程序员就可以访问任何与 ODBC 兼容的数据库,包括 MS SQL SERVER、 Access、 Oracle 等等。如果您是一个对数据库连接有一定了解的脚本编写人员,那么您将发现 ADO 命令语句并不复杂而且容易掌握。同样地,如果您是一个经验丰富的数据库编程人员,您将会正确认识 ADO 的先进的与语言无关性和查询处理功能。熟悉 VB 数据库编程的朋友会发现 ADO 与 RDO (Remote Data Objects) 有某种类似的地方。但据说 ADO 的访问的速度更快,内存需要更小。    下面给大家简要介绍一下利用 ASP 的 Database Access 组件通过 ADO 连接并操作 WEB 数据库的步骤    第一步 : 指定想要连接的数据库,有 DSN 和 DSN-less 两种方法。    DSN(Data Source Name 数据源名称 ): 建立一个系统数据源名称,方法如下 :    1、单击“开始”,选设置控制面板。    2、双击图标“32 位 ODBC” , 将弹出一个对话框,选标签“System DSN”    3、单击“Add”添加一个 DSN 入口 , 选择如“Microsoft Access Drive”并确认。    4、在“Data Source Name”栏里输入你希望指定的 DSN, 然后单击“Select”选择数据库存放位置,你可以按“Browse”来选取。    5、以上步骤完成后在 ASP 程序中指定 DSN,如下 :    < %connstr = "DSN"%>   DSN-less: 是另一种通过在 ASP 文件里直接指定数据库文件所在位置,而无需建立 DSN 的方法。由于许多公司没有自己的 WEB 服务器,他们的网站往往是存放在远端的虚拟服务器上,因此要建立和修改 DSN 的设置比较麻烦。而使用 DSN-less 方法直接指定远端数据库所在位置恰恰解决了这一问题,方法如下 : < % connstr = "DBQ="+server.mappath("database/source.mdb")+";DefaultDir=; DRIVER={Microsoft Access Driver (*.mdb)};DriverId=25;FIL=MS Access; ImplicitCommitSync=Yes;MaxBufferSize=512;MaxScanRows=8; PageTimeout=5;SafeTransactions=0;Threads=3;UserCommitSync=Yes;" %>    在指定了想要连接的数据库后,就可以通过以下方法连接并打开数据库 : < % Set Conn = Server.CreateObject("ADODB.Connection")Conn.Open constr %>   第二步 : 指定想要执行的 SQL 指令,可以使用 RecordSet。   当连接了数据库后就可以对数据库进行操作,比如查询、删除、更新等等,这些操作都是通过 SQL 指令来完成的,如下例在数据库表 datebase 中查询所有姓名中有“A”的记录 : < % sql="select * from datebase where name like 'A%%'" Set rs = Conn.Execute(sql) %>   尽管 Connection 对象简化了连接数据库和查询任务,但 Connection 对象仍有许多不足。确切地说,检索和显示数据库信息的 Connection 对象不能用于创建脚本,您必须确切知道要对数据库作出的更改,然后才能使用查询实现更改。对于检索数据、检查结果、更改数据库, ADO 提供了 Recordset 对象。正如它的名称所暗示的那样, Recordset 对象有许多您可以使用的特性,根据您的查询限制,检索并且显示一组数据库行,即记录。 Recordset 对象保持查询返回的记录的位置,允许您一次一项逐步扫描结果。根据 Recordset 对象的指针类型属性设置,您可以滚动和更新记录。数据库指针可以让您在一组记录中定位到特定的项。指针还用于检索和检查记录,然后在这些记录的基础上执行操作。 Recordset 对象有一些属性,可用于精确地控制指针的行为,提高您检查和更新结果的能力。    Recordset 的使用方法如下 :    Set rs = Server.CreateObject("ADODB.Recordset")    rs.Open SQL 指令 , Conn, 1, 1 ' 读取    或    rs.Open SQL 指令 , Conn, 1, 3 ' 新增、修改、或删除

59ita点com(我就爱TA)
2005-09-19 23:50
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
    当你用 ASP 编写服务器端应用程序时,必须依靠 ActiveX 组件来强大 Web 应用程序的功能,譬如:你需要连接数据库,对数据库进行在线操作等等。
   
    上两篇中作者给大家介绍了 AD Rotator、 Database Access 等组件的使用方法,今天我们接着来看看其它的一些 ASP 常用组件。
   
     一、 Browser Capabilities 组件众所周知,并不是所有浏览器都支持现今 Internet 技术的方方面面。有一些特性,某些浏览器支持而另一些浏览器却不支持,如 : ActiveX 控件、影像流、动态 HTML、 Flash 以及脚本程序等。使用 ASP 的 Browser Capabilities 组件,就能够设计“智能”的 Web 页,以适合浏览器性能的格式呈现内容。 Browser Capabilities 组件能够创建一个 BrowserType 对象,该对象提供带有客户端网络浏览器的功能说明的用户脚本。该组件之所以能识别客户浏览器的版本等信息,主要是因为当客户浏览器向服务器发送页面请求时,会自动发送一个 User Agent HTTP 标题,该标题是一个声明浏览器及其版本的 ASCII 字符串。 Browser Capabilities 组件将 User Agent 映射到在文件 Browscap.ini 中所注明的浏览器 , 并通过 BrowserType 对象的属性来识别客户浏览器。若该对象在 browscap.ini 文件中找不到与该标题匹配的项,那么将使用默认的浏览器属性。若该对象既未找到匹配项且 browscap.ini 文件中也未指定默认的浏览器设置,则它将每个属性都设为字符串 "UNKNOWN"。在默认情况下, browscap.ini 文件被存放在 WINDOWS\SYSTEM\INERSRV( 如果是 95/98+PWS4) 或 NT\SYSTEM32\INERSRV( 如果是 NT) 目录中,你可以自己编辑这个文本文件,以添加自己的属性或者根据最新发布的浏览器版本的更新文件来修改该文件。请看以下 checkCookie() 过程,使用 BrowserCap 对象的 Cookie 属性来判断客户端浏览器是否支持 Cookie,并返回信息 :
   
  &lt; %
  Sub checkCookie()
  Set BrowserCap=Server.CreateObject("MSWC.BrowserType")
  if BrowserCap.Cookie=True then
  response.write "你的浏览器支持 Cookie!"
  else
  response.write "对不起,你所使用的浏览器不支持 Cookie!"
  end if
  end Sub
  %&gt;
   
   
     有关 Browser Capabilities 组件的详细信息,请参见动态网站设计十八般武艺 --ASP 篇 (2)。
   
     二、 File Access 组件如果你的网龄足够大的话,你一定见过“恐龙时代”的 CGI 留言簿,那是 WEB 留言簿最早的雏形。那时候在基于 Internet 的 WEB 应用程序中连接服务器后端数据库还十分困难,因此留言簿中的历史信息并不是同如今一样存储在后端数据库中。那么这些数据究竟是保存在哪里的呢?答案就是“文本文件”, CGI 程序可以将从客户端接收的信息写进一个存放在服务器端的文本文件中,该文件可以是 HTML 文件或 TXT 等文件,这样就使得程序员们可以不通过同数据库连接就可以将客户信息保存下来,但是写此类 CGI 程序甚是烦琐,下面列出了一个此类程序的最简单的样本 :
   
  #!/usr/local/bin/perl
  # Perl Location one your server
  print "Content-type: text/plain\n\n";
  if($ENV{'REQUEST_METHOD'}eq"POST"){
  read(STDIN,$buffer,$ENV{'CONTENT_LENGTH'});
  }elsif($ENV{'REQUEST_METHOD'}eq"GET"){
  $buffer=$ENV{'QUERY_STIRNG'};
  }
  @pairs=split(/&amp;/,$buffer);
  foreach $pair(@pairs){
  ($name,$value)=split(/=/,$pair);
  $value=~tr/+//;
  $value=~s/%([a-f A-F 0-9][a-f A-f 0-9])/pack("C",hex($1))/eg;
  $FORM{$name}=$value;}
  $file_name="guestbook.txt";#File name
  #具体内容
  open(FILE,"&gt;&gt;$file_name")||die "打开文件错误";
  print FILE "记录时间":$date \n\n";
  print FILE "姓名":$FORM{'name'}";
  print FILE "单位":$FORM{'company'}\n";
  print FILE "电话":$FORM{'phone'}
  print FILE "地址":$FORM{'address'}\n";
  print FILE "邮编":$FORM{'zip'}
  print FILE "邮件地址":$FORM{'email'}\n";
  print FILE "返回意见":$FORM{'content'}
  close (FILE)
   
    大家可以感觉到,与 ASP 相比此类 CGI 程序的可读性和易操作性都较差。那么你一定想问 ASP 是否也能直接在服务器上写文件呢?答案当然是肯定的。但是聪明的朋友可能会想到,既然 ASP 同 WEB 数据库的连接如此便捷,我们又何需再将客户信息写在文本文件中呢, ASP 的这个功能岂不是画蛇添足?的确,对于那些我们常见的留言簿、 BBS 等 WEB 应用程序而言,无论是在程序的执行效率还是易用性上,我们都不可能再用写文本文件来替代数据库,但是在某些 WEB 应用领域里写文本文件既是一种规范也是一种相对数据库而较便捷的方法。如果你对 NT 较熟悉的话,你一定知道 NT 具有非常强大的安全机制,它可以将几乎所有的服务器操作和连接的信息自动保存在一个后缀名为 .log 的文件中,其实这种技术也完全可以被运用在 WEB 上,用来记录一些的客户登陆信息。下面的这段程序正是利用 ASP 读写文本文件的特性,在一个 WEB BBS 程序中创建自动记录每个用户发言记录的功能。
   
  &lt; %
  Set fs = CreateObject("Scripting.FileSystemObject")
  ForReading = 1
  '以只读模式打开文件。不能对此文件进行写操作。
  ForAppending = 8
  '打开文件并在文件末尾进行写操作。
  TristateUseDefault = -2
  TristateTrue = -1
  TristateFalse = 0
   
  '-----------写入系统log开始--------
  servermap=server.MapPath("\bbs\log\")
  '映射系统物理路径
  temp=servermap&amp;"\"&amp;year(date)&amp;month(date)&amp;"\"
  '获取系统物理路径和时间,并以此作为log文件存放的物理路径
  if Not fs.FolderExists(temp) then
  fs.CreateFolder(temp)
  end if
  '检测是否存在文件夹,否则自动创建
  dim syslog
  dim tempname
  tempname=date
  syslog=temp&amp;tempname&amp;".log"
  '文件名为e:\bbs\log\月份\月日.log
  li=user&amp;"&amp;"&amp;Now&amp;"&amp;"&amp;Request.ServerVariables("REMOTE_ADDR")&amp;"&amp;"&amp;tempfile&amp;"&amp;"&amp;letter&amp;"&amp;"&amp;title
  'log文件记录的格式为:用户名&amp;发信时间&amp;用户ip&amp;文件路径&amp;信区&amp;信件标题
  if fs.FileExists(syslog) then
  Set ss = fs.OpenTextFile(syslog,ForAppending,true)
  else
  set ss = fs.CreateTextFile(syslog,ForWriting,false)
  end if
  '检测log文件是否存在,如果存在则追加文件内容,反之则直接写文件
  ss.WriteLine(li)
  ss.Close
  '-----------log文件写入结束---------
  %&gt;
   
   
   
    如果你没有完全看懂上面的这段程序,就请听作者慢慢道来。 File Access 组件提供了可用来访问计算机文件系统的方法和属性。我们可以使用 File Access 组件创建 FileSystemObject 对象,以上程序的第一句就是利用 File Access 组件创建了一个名为 fs 的对象实例。在对象被创建后,你可以通过它访问文件,该对象没有属性,它唯一的意义就是创建、打开或读写文本文件。 FileSystemObject 对象有两种最常用的方法,一种用来创建文件,另一种是用来打开并读写文本文件。 CreateTextFile 方法获得你指定的文件名并创建该文件,它返回一个 TextStream 对象,你可以用该对象在文件被创建后操作该文件, CreateTextFile 方法的语法如下 :
    Set objTextStream=FileSystemObject.CreateTextFile(Filename,[Overwrite],[Unicode])
   
    下面作者给大家解释一下 CreateTextFile 方法的参数
   
    1、 Filename 包含文件路径名的字符串,可以是文件的全路径名,包括驱动器名和目录名,或者也可以只是文件名,如果只包含文件名的话,文件将被创建在站点的根目录下。
   
    2、 Overwrite 布尔量,设置成 False 时可以防止 FileSystemObject 对象在创建一个新文件时删除已存在的文件,该参数是可选的,如果没有赋值系统默认为 true,具有相同文件名的已有文件会被删掉。
   
    3、 Unicode 可选参数。布尔值指明是否以 Unicode 或 ASCII 文件格式创建文件。如果以 Unicode 文件格式创建文件,则该值为 True;如果以 ASCII 文件格式创建文件,则该值为 False。如果省略此部分,则假定创建 ASCII 文件。
   
    在前面的程序中我们用 set ss=fs.CreateTextFile(syslog,ForWriting,false) 来在 log 文件不存在的情况下创建文件并对文件进行写操作,这里的“ForWriting”表示写文件。
   
    与 CreateTextFile 方法不同, OpenTextFile 方法用来获得你指定的文件名并打开该文件,利用它所带的参数我们可以对文件进行各种不同的操作,和 CreateTextFile 方法一样, OpenTextFile 方法返回一个 TextStream 对象,使得你可以在文件被打开后操作该文件。 OpenTextFile 方法的语法如下 :
     Set objTextStream=FileSystemObject.OpenTextFile(Filename,[IOmode],[Create],[Format])
   
    参数说明如下 :
   
    1、 Filename 必须的变量,同 CreateTextFile 的 filename
   
    2、 IOmode 可选的常量,取值为下列两个常数之一 ForReading 或 ForAppending,如果 mode 为 1,文件以只读方式打开,如果为 8,则文件以追加的方式打开。
   
    3、 Create 可选的布尔量,指定如果你想打开的文件不存在是做什么操作,如果其值为 True,当文件不存在时就自动创建一个空的文件。如果为 False,就会在文件没找到时产生一个出错信息,其默认值是 False,建议将其设为 True,以避免在打开文件时检查是否出错。
     4、 Format 可选值,可以选择三种 Tristate 值分别指定文件的格式, -2、 -1、和 0 分别对应于系统缺省、 unicode 和 ASCII。
   
    在打开或创建了文本文件后,就得到一个 TextStream 对象,该对象有一个光标,就好象是在字处理程序中的光标一样,指出接下来要敲入的字符将出现的位置,它同时也指出你要读取的字符的位置。不能通过 CreatObject 来创建一个 TextStream 对象,得到 TextStream 对象的唯一方法是如前所述的用 FileSystemObject 对象打开一个存在的文本文件或者创建一个新的文件。
     下面列出了 TextStream 对象的属性和方法
   
     TextStream.AtEndOfLine 只读布尔量,当光标在当前行的末尾时,其值为 true,反之则为 false
   
     TextStream.AtEndOfStream 只读布尔量,如果光标在流的末尾时,其值为 true,否则为 false
   
     TextStream.Column 只读的整数,统计从行首到当前光标位置之间的字符数
   
     TextStream.Line 只读的整数,指明光标所在行在整个文件中的行号
   
     TextStream.close() 关闭流以及对应的文本文件
   
     TextStream.read(Num) 指定从光标的当前位置开始从文本文件中读取一定数目的字符
   
     TextStream.readall() 将整个流读入一个字符串中
   
     TextStream.readline() 将一整行的字符读入一个字符串中
   
     TextStream.write(text) 将一个字符串写入流中
   
     TextStream.writeline() 将一个文本串写入流中
   
     TextStream.skip(Num) 在流中,将光标的位置移动一定数目的字符串长度
   
     TextStream.skiplines() 在流中,将光标移动一定数目的行数
   
     TextStream.writeblank 将一定数目的空行写入流中
   
     lines(num)
   
    相信大家现在已经可以感觉到 ASP File Access 组件的强大功能了,其实它远不仅仅可以写一些 log 文件,通过它你甚至可以毫不费力的远程自动更新你的网站,你只要把固定格式的文本文件传送到远端的服务器上,通过 File Access 组件读取文件,并自动生成全新 HTML 页面即可,而不必再辛辛苦苦地一个一个地更新 HTML 文件。如果你有兴趣,你完全可以用 ASP 的 File Access 组件写一个自己的全自动 HTML 生成器,充分享受维护网站的超前轻松感。

59ita点com(我就爱TA)
2005-09-19 23:51
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
    什么是 ADO 存取数据库时的分页显示?如果你使用过目前众多网站上的电子公告板程序的话,那你应该会知道电子公告板程序为了提高页面的读取速度,一般不会将所有的帖子全部在一页中罗列出来,而是将其分成多页显示,每页显示一定数目的帖子数,譬如 20 条。想不想了解如何实现分页显示?请看本文!
   
    《动态网站设计十八般武艺 --ASP 篇》一文从第一期至今已和朋友们一起度过了大半个年头,相信通过在这一段时间中的学习、实践到再学习、再实践,大家已经能够熟练运用 ASP 的内建对象、 ActiveX 组件去编写一些基本的 ASP 应用程序。从我收到的朋友们的来信中可以明显的感觉到,大家的 ASP 功力正不断地提升。最近很多朋友来信希望我写一些 ASP 在现实运用中的实例。因此,从本期开始我决定将《动态网站设计十八般武艺 --ASP 篇》的定位从介绍和学习 ASP 基础知识转向到 ASP 实际运行的探讨和深化。应朋友们的要求,在本期中我将给大家着重谈一谈“ADO 存取数据库时如何分页显示”的问题。
    什么是 ADO 存取数据库时的分页显示?如果你使用过目前众多网站上的电子公告板程序的话,那你应该会知道电子公告板程序为了提高页面的读取速度,一般不会将所有的帖子全部在一页中罗列出来,而是将其分成多页显示,每页显示一定数目的帖子数,譬如 20 条。这就是数据库查询的分页显示,如果你还不明白,去看看 yahoo 等搜索引擎的查询结果就会明白了。
   
    那么究竟如何才能做到将数据库的查询结果分页显示呢?其实方法有很多,但主要有两种:
   
    一、将数据库中所有符合查询条件的记录一次性的都读入 recordset 中,存放在内存中,然后通过 ADO Recordset 对象所提供的几个专门支持分页处理的属性: PageSize( 页大小 )、 PageCount( 页数目 ) 以及 AbsolutePage( 绝对页 ) 来管理分页处理。
   
    二、根据客户的指示,每次分别从符合查询条件的记录中将规定数目的记录数读取出来并显示。
   
    两者的主要差别在于前者是一次性将所有记录都读入内存然后再根据指示来依次做判断分析从而达到分页显示的效果,而后者是先根据指示做出判断并将规定数目的符合查询条件的记录读入内存,从而直接达到分页显示的功能。
   
    我们可以很明显的感觉到,当数据库中的记录数达到上万或更多时,第一种方法的执行效率将明显低于第二种方法,因为当每一个客户查询页面时都要将所有符合条件的记录存放在服务器内存中,然后在进行分页等处理,如果同时有超过 100 个的客户在线查询,那么 ASP 应用程序的执行效率将大受影响。但是,当服务器上数据库的记录数以及同时在线的人数并不是很多时,两者在执行效率上是相差无几的,此时一般就采用第一种方法,因为第一种方法的 ASP 程序编写相对第二种方法要简单明了得多。
   
    在这里作者就以我们常见的 ASP BBS 程序为例,来给大家分析一下如何在 BBS 程序里实现分页显示功能,由于我们一般使用的 BBS 程序的数据库记录数和同时访问的人数都不会太多,所以以下程序实例是使用的先前所介绍的第一种分页显示方法。
   
     进行 ADO 存取数据库时的分页显示,其实就是对 Recordset 的记录进行操作。所以我们首先必须了解 Reordset 对象的属性和方法:
     BOF 属性:目前指标指到 RecordSet 的第一笔。
   
     EOF 属性:目前指标指到 RecordSet 的最后一笔。
   
     Move 方法:移动指标到 RecordSet 中的某一条记录。
   
     AbsolutePage 属性:设定当前记录的位置是位于哪一页 AbsolutePosition 属性:目前指标在 RecordSet 中的位置。
   
     PageCount 属性:显示 Recordset 对象包括多少“页”的数据。
   
     PageSize 属性:显示 Recordset 对象每一页显示的记录数。
   
     RecordCount 属性:显示 Recordset 对象记录的总数。
   
     下面让我们来详细认识一下这些重要的属性和方法
   
     一、 BOF 与 EOF 属性
   
     通常我们在 ASP 程序中编写代码来检验 BOF 与 EOF 属性,从而得知目前指标所指向的 RecordSet 的位置,使用 BOF 与 EOF 属性,可以得知一个 Recordset 对象是否包含有记录或者得知移动记录行是否已经超出该 Recordset 对象的范围。
   
     如: &lt; % if not rs.eof then ... %&gt;
   
     &lt; % if not (rs.bof and rs.eof) %&gt;
   
    若当前记录的位置是在一个 Recordset 对象第一行记录之前时, BOF 属性返回 true,反之则返回 false。
   
    若当前记录的位置是在一个 Recordset 对象最后一行记录之后时, EOF 属性返回 true,反之则返回 false。
   
    BOF 与 EOF 都为 False:表示指标位于 RecordSet 的当中。
   
    BOF 为 True:目前指标指到 RecordSet 的第一笔记录。 EOF 为 True:目前指标指到 RecordSet 的最后一笔记录。
   
    BOF 与 EOF 都为 True:在 RecordSet 里没有任何记录。
   
    二、 Move 方法
   
    您可以用 Move 方法移动指标到 RecordSet 中的某一笔记录,语法如下:
   
    rs.Move NumRecords,Start
   
    这里的“rs”为一个对象变量,表示一个想要移动当当前记录位置的 Recordset 对象;“NumRecords”是一个正负数运算式,设定当前记录位置的移动数目;“start”是一个可选的项目,用来指定记录起始的标签。
   
     所有的 Recordset 对象都支持 Move 方法,如果 NumRecords 参数大于零,当前记录位置向末尾的方向移动;如果其小于零,则当前记录位置向开头的方向移动;如果一个空的 Recordset 对象调用 Move 方法,将会产生一个错误。
   
     MoveFirst 方法:将当前记录位置移至第一笔记录。
   
     MoveLast 方法:将当前记录位置移至最后一笔记录。
   
     MoveNext 方法:将当前记录位置移至下一笔记录。 MovePrevious 方法:将当前记录位置移至上一笔记录。
   
     Move [n] 方法:移动指标到第 n 笔记录, n 由 0 算起。
   
    三、 AbsolutePage 属性
   
    AbsolutePage 属性设定当前记录的位置是位于哪一页的页数编号;使用 PageSize 属性将 Recordset 对象分割为逻辑上的页数,每一页的记录数为 PageSize( 除了最后一页可能会有少于 PageSize 的记录数 )。这里必须注意并不是所有的数据提供者都支持此项属性,因此使用时要小心。
   
    与 AbsolutePosition 属性相同, AbsolutePage 属性是以 1 为起始的,若当前记录为 Recordset 的第一行记录, AbsolutePage 为 1。可以设定 AbsolutePage 属性,以移动到一个指定页的第一行记录位置。
   
    四、 AbsolutePosition 属性
   
    若您需要确定目前指标在 RecordSet 中的位置,您可以用 AbsolutePosition 属性。
   
    AbsolutePosition 属性的数值为目前指标相对於第一笔的位置,由 1 算起,即第一笔的 AbsolutePosition 为 1。
   
    注意 , 在存取 RecordSet 时,无法保证 RecordSet 每次都以同样的顺序出现。
   
    若要启用 AbsolutePosition,必须先设定为使用用户端 cursor( 指针 ), asp 码如下:
   
    rs2.CursorLocation = 3
   
    五、 PageCount 属性
   
    使用 PageCount 属性,决定 Recordset 对象包括多少“页”的数据。这里的“页”是数据记录的集合,大小等于 PageSize 属性的设定,即使最后一页的记录数比 PageSize 的值少,最后一页也算是 PageCount 的一页。必须注意也并不是所有的数据提供者都支持此项属性。
   
    六、 PageSize 属性
   
    PageSize 属性是决定 ADO 存取数据库时如何分页显示的关键,使用它就可以决定多少记录组成一个逻辑上的“一页”。设定并建立一个页的大小,从而允许使用 AbsolutePage 属性移到其它逻辑页的第一条记录。 PageSize 属性能随时被设定。
   
   
    七、 RecordCount 属性
   
    这也是一个非常常用和重要的属性,我们常用 RecordCount 属性来找出一个 Recordset 对象包括多少条记录。如: &lt; % totle=RS.RecordCount %&gt;
   
    在了解了 Recordset 对象的以上属性和方法后,我们来考虑一下,如何运用它们来达到我们分页显示的目的。首先,我们可以为 PageSize 属性设置一个值,从而指定从记录组中取出的构成一个页的行数;然后通过 RecordCount 属性来确定记录的总数;再用记录总数除以 PageSize 就可得到所显示的页面总数;最后通过 AbsolutePage 属性就能完成对指定页的访问。好象很并不复杂呀,下面让我们来看看程序该如何实现呢?
   
    我们建立这样一个简单的 BBS 应用程序,它的数据库中分别有以下五个字段:“ID”,每个帖子的自动编号;“subject”,每个帖子的主题;“name”,加帖用户的姓名;“email”,用户的电子邮件地址;“postdate”,加帖的时间。数据库的 DSN 为“bbs”。我们将显示帖子分页的所有步骤放在一个名为“ShowList()”的过程中,方便调用。程序如下:
   
  '----BBS 显示帖子分页----
  &lt; % Sub ShowList() %&gt;
  &lt; %
  PgSz=20 '设定开关,指定每一页所显示的帖子数目,默认为20帖一页
  Set Conn = Server.CreateObject("ADODB.Connection")
  Set RS = Server.CreateObject("ADODB.RecordSet")
  sql = "SELECT * FROM message order by ID DESC"
  '查询所有帖子,并按帖子的ID倒序排列
  Conn.Open "bbs"
  RS.open sql,Conn,1,1
  If RS.RecordCount=0 then
  response.write "&lt; P&gt;&lt; center&gt;对不起,数据库中没有相关信息!&lt; /center&gt;&lt; /P&gt;"
  else
  RS.PageSize = Cint(PgSz) '设定PageSize属性的值
  Total=INT(RS.recordcount / PgSz * -1)*-1 '计算可显示页面的总数
  PageNo=Request("pageno")
  if PageNo="" Then
  PageNo = 1
  else
  PageNo=PageNo+1
  PageNo=PageNo-1
  end if
  ScrollAction = Request("ScrollAction")
  if ScrollAction = " 上一页 " Then
  PageNo=PageNo-1
  end if
  if ScrollAction = " 下一页 " Then
  PageNo=PageNo+1
  end if
  if PageNo &lt; 1 Then
  PageNo = 1
  end if
  n=1
  RS.AbsolutePage = PageNo
  Response.Write "&lt; CENTER&gt;"
  position=RS.PageSize*PageNo
  pagebegin=position-RS.PageSize+1
  if position &lt; RS.RecordCount then
  pagend=position
  else
  pagend= RS.RecordCount
  end if
  Response.Write "&lt; P&gt;&lt; font color='Navy'&gt;&lt; B&gt;数据库查询结果:&lt; /B&gt;"
  Response.Write "(共有"&amp;RS.RecordCount &amp;"条符合条件的信息,显示"&amp;pagebegin&amp;"-"&amp;pagend&amp;")&lt; /font&gt;&lt; /p&gt;"
  Response.Write "&lt; TABLE WIDTH=600 BORDER=1 CELLPADDING=4 CELLSPACING=0 BGCOLOR=#FFFFFF&gt;"
  Response.Write "&lt; TR BGCOLOR=#5FB5E2&gt;&lt; FONT SIZE=2&gt;&lt; TD&gt;&lt; B&gt;主题&lt; /B&gt;&lt; /TD&gt;&lt; TD&gt;&lt; B&gt;用户&lt; /B&gt;&lt; /TD&gt;&lt; TD&gt;&lt; B&gt;Email&lt; /B&gt;&lt; /TD&gt;&lt; TD&gt;&lt; B&gt;发布日期&lt; /B&gt;&lt; /TD&gt;&lt; /FONT&gt;&lt; TR BGCOLOR=#FFFFFF&gt;"
  Do while not (RS is nothing)
  RowCount = RS.PageSize
  Do While Not RS.EOF and rowcount &gt; 0
  If n=1 then
  Response.Write "&lt; TR BGCOLOR=#FFFFFF&gt;"
  ELSE
  Response.Write "&lt; TR BGCOLOR=#EEEEEE&gt;"
  End If
  n=1-n %&gt;
  &lt; TD&gt;&lt; span style="font-size:9pt"&gt;&lt; A href='view.asp?key=&lt; % =RS("ID")%&gt;'&gt;&lt; % =RS("subject")%&gt;&lt; /A&gt;&lt; /span&gt;&lt; /td&gt;
  &lt; TD&gt;&lt; span style="font-size:9pt"&gt;&lt; % =RS("name")%&gt;&lt; /A&gt;&lt; /span&gt;&lt; /td&gt;
  &lt; TD&gt;&lt; span style="font-size:9pt"&gt;&lt; a href="mailt&lt; % =RS("email")%&gt;"&gt;&lt; % =RS("email")%&gt;&lt; /a&gt;&lt; /span&gt; &lt; /TD&gt;
  &lt; TD&gt;&lt; span style="font-size:9pt"&gt;&lt; % =RS("postdate")%&gt;&lt; /span&gt; &lt; /td&gt;
  &lt; /TR&gt;
  &lt; %
  RowCount = RowCount - 1
  RS.MoveNext
  Loop
  set RS = RS.NextRecordSet
  Loop
  Conn.Close
  set rs = nothing
  set Conn = nothing
  %&gt;
  &lt; /TABLE&gt;
  &lt; FORM METHOD=GET ACTION="list.asp"&gt;
  &lt; INPUT TYPE="HIDDEN" NAME="pageno" VALUE="&lt; % =PageNo %&gt;"&gt;
  &lt; %
  if PageNo &gt; 1 Then
  response.write "&lt; INPUT TYPE=SUBMIT NAME='ScrollAction' VALUE=' 上一页 '&gt;"
  end if
  if RowCount = 0 and PageNo &lt; &gt;Total then
  response.write "&lt; INPUT TYPE=SUBMIT NAME='ScrollAction' VALUE=' 下一页 '&gt;"
  end if
  response.write "&lt; /FORM&gt;"
  End if
  %&gt;
  &lt; % End Sub %&gt;
   
    相信大家都应该能完全读懂上面的程序,因此作者就不在此详细解释了。值得注意的是在这段程序中运用了一个小技巧 &lt; INPUT TYPE="HIDDEN" NAME="pageno" VALUE="&lt; % =PageNo %&gt;"&gt;,这是用来在每次调用该 ASP 文件时传递数据的“暗道”,由于我们需要在每次调用程序时传递代表当前页码的参数,可能大家会想到使用 session,但是从节省系统资源和通用性来讲,用这样一个隐藏的 form 来传递数据将会达到更好的效果。
   
    好了,又到了说再见的时候了,如果你没完全看懂本篇中所列的程序,那你必须加把油,看一看 VbScript 的语法;如果你还有某些疑问,可以“妹儿”我,我将尽力解答;如果你有什么更好的建议也千万要来信告诉我哦 :)
   

59ita点com(我就爱TA)
2005-09-19 23:52
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
  无论你相不相信,通过 asp,可能可以很方便地入侵 web server、窃取服务器上的文件、捕获 web 数据库等系统的用户口令,甚至恶意删除服务器上的的文件,直至造成系统损坏,这些都决非耸人听闻,而且都确确实实发生过,本文将向你一一揭示这些 asp 存在的漏洞,并提出一些防范意见。
   
    上一篇中给大家着重谈了“ADO 存取数据库时如何分页显示”的问题,有位朋友来信给我指出我在计算页面总数时忽略了 Recordset 对象的一个重要参数“PageCount”,它能在给 Pagesize 赋值后自动得出页面的总数,而无须用“INT(RS.recordcount/PgSz*-1)*-1”这样繁琐的公式。我要感谢这位朋友热心地给我指出程序中的不足,由于这个程序是我在很久以前写的,因为在分页显示的时候记录的总数不一定能整除页面显示记录的数目,而当时我又不能肯定 PageCount 是否能正确得出页面的数目,所以偷懒写了这个公式:),说实话我到现在还都没试过用 pagecount,有兴趣的朋友千万要试一下哦,可别学我的懒惰呀。
   
    最近我在 chinaasp 的 bbs 上讨论问题时发现很多朋友对于 asp 的一些安全性问题不甚了解,甚至不知道如何解决最常见的 asp::$DATA 显示源代码的问题,因此我觉得非常有必要在这里给广大朋友们重点谈一谈这个问题,在征得 chinaasp 飞鸟的同意下,我将他曾经写过的一点关于 asp 漏洞的介绍加上我自己的一些实践经验拿出来给大家详细分析一下这个对于 webmaster 来说至关重要的 asp 的安全性问题。
   
    当去年 ::$DATA 的漏洞被发现并公布的第二天,我曾经检测了当时国内大部分运用 asp 的站点,其中百分之九十九都存在以上可以看见源代码的问题,当日我甚至在微软的站点上抓下了 search.asp 这个文件的源代码。可能你会觉得看到源代码并没有什么大碍,如果作为 webmaster 的你这么想就大错特错了。譬如,如果 asp 程序员将站点的登陆密码直接写在 asp 里,那么一旦源码被发现,他人就可以很容易的进入本不该被看到的页面,我就曾经利用这个方法免费成为了一个收费网站的成员(大家可别揭发我哦!),而且很多数据库的连接用户名和密码也都是直接写在 asp 里,一旦被发现,如果你的数据库允许远程访问而且没有设防的话就相当危险了。在一些用 asp 开发的 bbs 程序中,往往使用的是 access mdb 库,如果 mdb 库存放的路径被获知,数据库就很有可能被他人下载,加之如果数据库里含有的密码不加密,那就非常危险了,获取密码的人如果有意进行恶意破坏,他只需要以 admin 身份登陆删除所有 bbs 里的帖子,就够你呛的了。下面列出了目前已经发现的一些漏洞,希望大家提高警惕一、经过实验我们发现, win95+pws 上运行 ASP 程序,只须简单地在浏览器地址栏的 asp 文件名后多加一个小数点 ASP 程序就会被下载下来。 IIS3 也存在同样的问题,如果你目前还在使用 IIS3 一定要测试一下。
    二、 iis2、 iis3、 iis4 的一个广为人知的漏洞就是 ::$DATA,通过它使用 ie 的 view source 或 netscape 直接访问该 asp 文件就能轻而易举地看到 asp 代码。 win98+pws4 不存在这个漏洞。
   
    究竟是什么原因造成了这种可怕的漏洞呢?究其根源其实是 Windows NT 特有的文件系统在做怪。有一点常识的人都知道在 NT 提供了一种完全不同于 FAT 的文件系统: NTFS,这种被称之为新技术文件系统的技术使得 NT 具有了较高的安全机制,但也正是因为它而产生了不少令人头痛的隐患。大家可能不知道, NTFS 支持包含在一个文件中的多数据流,而这个包含了所有内容的主数据流被称之为“DATA”,因此使得在浏览器里直接访问 NTFS 系统的这个特性而轻易的捕获在文件中的脚本程序成为了可能。然而直接导致 ::$DATA 的原因是由于 IIS 在解析文件名的时候出了问题,它没有很好地规范文件名。
    我们该如何解决这个问题呢?办法有几种:
   
    a、是将 .asp 文件存放的目录设置为不可读(ASP 仍能执行),这样 html、 css 等文件就不能放在这个目录下,否则它们将不能被浏览。
   
    b、是安装微软提供的补丁程序,下载的地址如下(注意针对不同的系统有不同的补丁):
   
    该补丁是针对 IIS3, Intel 平台
   
    ftp.
   
    该补丁是针对 IIS3, Intel 平台
   
    ftp.
   
    该补丁是针对 IIS4, Alpha 平台
   
    ftp.
   
    该补丁是针对 IIS4, Alpha 平台
   
    ftp.
   
    c、是在服务器上安装 ie4.01sp1,这个是否有效,作者本人没具体试过。
   
    d、存粹作者的个人意见,尽量安装英文版的 NT,而不要使用中文版,究其原因作者也说不清,只是根据实践经验英文版的 NT 较中文版 bug 少,如果哪位朋友知道原因千万要告诉我。
   
   
   软件首页 | 软件新闻 | 软件评测 | 软件应用 | 信息安全 | 创意设计 | 开发特区 | 精品导用
   
   特色专区: 教你学电脑 | 组网专栏 | 素材下载 | Flash 剧场 | CG专栏
   
   
  网络学院 &gt; 开发教室 &gt; 网站开发 &gt; ASP
   ASP教程:第十八篇 堵住ASP漏洞
   出处:PConline
  责任编辑:pjl
   
  [01-11-25 14:40] 作者:书生
   
    三 . 支持 ASP 的免费主页空间以及虚拟主机服务的服务器面临的问题
   
    1、服务器上的 ASP 代码很可能被人其他拥有 asp 权限的人非法获取。
   
    举个很简单的例子,在微软提供的 ASP1.0 的例程里有一个 .asp 文件专门用来查看其它 .asp 文件的源代码,该文件为 ASPSamp/Samples/code.asp。如果有人把这个程序上传的服务器,而服务器端没有任何防范措施的话,他就可以很容易地查看他人的程序。
    例如 :
   
    code.asp?source=/directory/file.asp
   
    2、使用的 ACCESS mdb 数据库可能被人下载一般来说在提供 asp 权限的免费主页服务器上不可能提供代为设定 DSN 的服务,因此 asp 程序使用的数据库通常都局限在使用 mdb 库,而 mdb 远端数据库所在的位置是使用我们在第十四期中讲到过的 DSN-less 方法直接在 asp 中指定的,方法如下 :
   
     &lt; %connstr = "DBQ="+server.mappath("database/source.mdb")+";DefaultDir=;DRIVER={Microsoft Access Driver (*.mdb)};DriverId=25;FIL=MS Access;ImplicitCommitSync=Yes;MaxBufferSize=512;MaxScanRows=8;PageTimeout=5; SafeTransactions=0;Threads=3;UserCommitSync=Yes;"%&gt;
    正如前文所言,在这种情况下 mdb 库很可能被他人下载,从而造成诸如密码等的泄露。
   
    所以,作为 webmaster 应该采取一定的措施,严禁 code.asp 之类的程序(似乎很难办到 , 但可以定期检索特征代码),限制 mdb 的下载。
   
    3、来自强大的 filesystemobject 组件的威胁
   
    IIS3、 IIS4 的 ASP 的文件操作都可以通过 filesystemobject 实现,包括文本文件的读写目录操作、文件的拷贝改名删除等,但是这个强大的功能也留下了非常危险的“后门”。利用 filesystemobjet 可以篡改下载 fat 分区上的任何文件。即使是 ntfs 分区,如果权限没有设定好的话,同样也能破坏,一不小心你就可能遭受“灭顶之灾”。遗憾的是很多 webmaster 只知道让 web 服务器运行起来,很少对 ntfs 进行权限设置,而 NT 目录权限的默认设置偏偏安全性又低得可怕。因此,如果你是 Webmaster,作者强烈建议你密切关注服务器的设置,尽量将 web 目录建在 ntfs 分区上,目录不要设定 everyone full control,即使是是管理员组的成员一般也没什么必要 full control,只要有读取、更改权限就足够了。
    四、 ASP 应用程序可能面临的攻击过去许多 Internet 上 CGI 写的留言本或 BBS 是把客户输入的留言变为一个变量,然后再把这个变量插入到显示留言的 HTML 文件里,因此客户输入的文本如要在 HTML 文件里显示就得符合 HTML 标准,而 CGI 程序里一般都加入了特定的 HTML 语言。当客户输入内容,插入 HTML 文件时,即同时插入到了头尾 HTML 语句中,如:
   
     &lt; font&gt; 客户输入的变量 &lt; /font&gt; 但如果把前后的 HTML 标记给敝屏了,就可以做很多事情了。
   
    如输入时打上:
   
     &lt; /font&gt; 符合 HTML 标准的语句 &lt; font&gt; 前后的 &lt; font&gt; 是用来敝屏 CGI 中的 HTML 语句用的。插入到 HTML 文件里的就变成了:
   
     &lt; font&gt;&lt; /font&gt; 符合 HTML 标准的语句 &lt; font&gt;&lt; /font&gt; 由于这样一个特性,使得写个 javascript 的死循环变得非常容易,只要在输入框中输入:
   
    &lt; a href="URL" onMouseover="while(1){window.close('/')}"&gt; 或 &lt; a herf="URL" onMousever="while(ture){window.close('/')}"&gt; 那么就能让其他查看该留言的客户的浏览器因死循环而死掉。 ASP 开发的程序同样可能存在这个问题,因此当你用 asp 编写类似程序时应该做好对此类操作的防范,譬如可以写一段程序判断客户端的输入,并屏蔽掉所有的 HTML、 Javascript 语句。
   
    看完本期后,如果你非常的震惊,那么你必须彻底对你现有的网站或 asp 程序进行一翻检测,看看是否存在上述漏洞。如果你对文中所谈到的漏洞都有所了解并已有足够的对策,那么在恭喜你的同时,还是要提醒你经常查看你的网站和 asp 程序,如果你有数据库也应该经常查看,以防他人利用一些我们未知的漏洞进行攻击。最后,如果你对本文所谈论的 asp 安全性问题有什么独特的见解,或对漏洞有新的发现,希望能来信同我探讨。

59ita点com(我就爱TA)
2005-09-19 23:53
belin2000
Rank: 3Rank: 3
等 级:论坛游侠
威 望:5
帖 子:975
专家分:194
注 册:2004-6-2
得分:0 
  当ASP以其灵活、简单、实用、强大的特性迅速风靡全球网站的时候,其本身的一些缺陷、漏洞也正威胁着所有的网站开发者,继上一篇中介绍了一些IIS的系统漏洞及ASP的安全问题后,本期中将针对最新的ASP、IIS安全漏洞进行详细的探讨,请所有的ASP网站开发者密切关注,提高警惕。
   
    本月初微软再次被指责对其出品的WEB服务器软件的安全问题不加重视。在微软的流行产品IIS SEVER4.0中被发现存在一种被称为“非法HTR请求”的缺陷。据微软称,此缺陷在特定情况下会导致任意代码都可以在服务器端运行。但用发现这一漏洞的Internet安全公司eEye的CEO Firas Bushnaq的话说:这只是冰山一角而已。Bushnaq说,微软隐瞒了些情况,比如黑客可以利用这一漏洞对IIS服务器进行完全的控制,而恰恰许多电子商务站点是基于这套系统的。
     下面罗列出了该IIS系统漏洞的详细情况:
   
     IIS的最新安全漏洞
   
     受影响的系统:
   
     Internet Information Server 4.0 (IIS4)
   
     Microsoft Windows NT 4.0 SP3 Option Pack 4
   
     Microsoft Windows NT 4.0 SP4 Option Pack 4
   
     Microsoft Windows NT 4.0 SP5 Option Pack 4
   
     公布日期:6.8.1999
   
     microsoft已经证实了这个漏洞,但目前还没有提供可用的补丁程序。
   
     微软安全公告 (MS99-019):
   
     主题:"非正常的 HTR 请求" 漏洞
   
     发布时间: 6.15.1999
   
    摘要:
   
    微软已经证实在其发布的WEB服务器产品Internet Information Server 4.0中存在一个严重的系统漏洞,该漏洞导致对于IIS服务器的“服务拒绝攻击”,在这种情况下,可能导致任何2进制代码在服务器上运行。有关该漏洞的补丁将在近期发布,请所有IIS用户密切关注。
    漏洞介绍:
   
    IIS支持多种需要服务器端处理的文件类型,譬如:ASP、ASA、IDC、HTR,当一个WEB用户从客户端请求此类文件时,相应的DLL文件将自动对其进行处理。然而在ISM.DLL这个负责处理HTR文件的文件中被发现存在严重的安全漏洞。(注:HTR文件本身是用来远程管理用户密码的)
   
    该漏洞包含了一个在ISM.DLL中未经验证的缓冲,它可能对WEB服务器的安全运作造成两方面的威胁。首先,是来自服务拒绝攻击的威胁,一个来自非正常的对.HTR文件请求将导致缓存溢出,从而直接导致IIS崩溃,当这种情况发生时,无须重启服务器,但是IIS WEB 服务器必须重新启动。另一个威胁更令人头痛,通过使用一个精心构建过的文件请求将可以利用标准的缓存溢出手段导致2进制代码在服务器端运行,在这种情况下,什么都可能发生!该漏洞不包括提供用来管理用户密码的功能的.HTR文件。
    原理分析:
   
    至少在一个IIS的扩展名中(例如:ASP,IDC,HTR)存在溢出。我们推测溢出将在IIS把完整的URL传递给DLL去处理扩展名时发生。如果ISAPI DLL 没有正确的检查限制范围从而导致INETINFO.EXE产生一个溢出,用户就从可以远端执行2进制代码。攻击方法:向IIS发一个如下的HTTP请求:"GET /[overflow].htr HTTP/1.0",IIS将崩溃。这里的[overflow]可以是3K长的代码。
   
    大家可能对.HTR文件不是很熟悉,其实IIS具有让NT用户通过WEB目录/iisadmpwd/更改自己的口令的能力。而这个功能正是由一组.HTR文件和ISAPI的一个扩展DLL: ISM.DLL实现的。当一个完整的URL传递到ISM.DLL时,由于没有适当的大小限制的检查,就会导致溢出产生,从而使得服务器崩溃。HTR/ISM.DLL ISAPI 是IIS4缺省安装。
    解决途径:
   
    由于目前微软尚未发布可供使用的补丁程序,因此我们只能做一些应急的防范。
   
    1、将.HTR扩展名从ISAPI DLL 的列表中删除
   
    在你的NT桌面上,点击“开始”—&gt;“程序”—&gt;“Windows NT 4.0 Option Pack”—&gt;“Microsoft Internet Information Server”—&gt;“Internet 服务管理器”;双击“Internet Information Server”;鼠标右键单击计算机名称并选择“属性”;在“主属性”下拉式菜单中选择“WWW服务”并点击“编辑”按钮;选择“主目录”文件夹,并点击“配置”按钮,在“应用程序映射”列表框中选中.HTR的相关映射,选择“删除”,并确定。
     2、安装微软提供的补丁程序,请密切关注以下网址
   
     http://www.
   
     http://www.
   
    可能一些朋友会感到不解,为什么我在ASP篇17、18期连续利用两大篇幅着重讨论IIS、ASP的安全性问题,如果你是一个WEB开发者、ASP程序员,我想你就应该能够体会我的用意。我们进行网络编程、开发交互性的网站,当然首先是为了发展、建设自身网站,但是这一些都是建立在安全的基础上,这里的安全包括对自己辛辛苦苦开发的ASP或其他网络应用程序代码的保护、确保网站服务器安全正常的运行、确保用户信息的安全及认证等等,当今后电子商务成为真正广泛运作的一种商务运行手段后,安全性更是关键之关键。我们中的很多朋友在作为ASP程序员的同时又身兼网络管理员的职责,因此熟悉系统的运作、及时了解系统漏洞、第一时间解决安全性问题就显得十分重要和必要,因此在本文的结尾,作者将整理的一些关于NT、IIS系统配置的安全性建议罗列出来,希望能给大家一些帮助。
    1、使用最新版本的Microsoft Internet Information Server4.0,并安装NT最新版本的Service Pack5,服务器的文件系统不要使用FAT,应该使用NTFS。
   
    2、把IIS中的sample、scripts、iisadmin和msadc等web目录设置为禁止匿名访问并限制IP地址。在微软还没有提供补丁之前,把ism.dll有关的应用程序映射删除。
   
    3、有条件的话就采用防火墙机制,最简单的如web服务开在前台,目录放在后台,如果能一个服务一台机当然最好。
   
    4、Web目录,CGI目录,scripts目录和winnt目录等重要目录要用NTFS的特性设置详细的安全权限,包含注册表信息的Winnt目录只允许管理员完全控制,一般的用户只读的权限也不要给。凡是与系统有关的重要文件,除了Administrator,其它帐号都应该设置为只读权限,而不是everyone/完全控制 。
   
    5、只开你需要的服务,block掉所有不应该打开的端口,如NetBios端口139,这是一个典型的危险端口;怎样禁止这些端口?除了使用防火墙外,NT的Tcp/IP设置里面也提供了这种功能:打开控制面板-网络-协议-TCP/IP-属性-高级-启用安全机制-配置,这里面提供了TCP和UDP端口的限制和IP协议的限制功能。
   
    6、管理员的帐号要设置得复杂一些,建议加入特殊字符。
   
    7、把FTP,Telnet的TCP端口改为非标准端口,通常我都是设置到10000~65000的范围
   
    8、删除可以删除的所有共享,包括打印机共享和隐藏的共享如ICP$,Admin$等,微软说这些特殊共享资源很重要,大多数情况下不能删除,而实际上放在Internet上的机器大多数不需要共享。
   
    IPC$: 适用于远程管理计算机和查看共享资源,在网上最好不要用
   
    Admin$: 实际上就是 c:\winnt,也没有必要共享
   
    C$: 登录为Admin和Backup-operator的用户可以用\\计算机名\C$的方式访问C盘,虽然仅限于局域网,但是远程黑客也有办法伪装成局域网的登录用户,所以都应该关掉。
   
    Print$: 这是放打印机驱动程序的目录,与上面的一样也是个很危险的入口。
   
    Netlogon: 这是处理域登录请求的共享。如果你的机器为主域控制器,域内有其它机器要登录进来,就不要删除它,否则照样可以删除。
   
    如何关闭这些共享?用“服务器管理器”—&gt;“共享目录”—&gt;“停止共享”
   
    9、将ASP的目录集中管理,ASP的程序目录设置详尽的访问权限,一般建议不要使用“读”权限。
   
    10、把winnt下的sam._文件改名,实践证明这个可能泄露密码的文件可以删除不要。
   
    11、对于已知的NT安全漏洞,都应该在自己的机器上做测试检查。并及时安装补丁程序。
   
    12、有必要的情况下采用IIS4.0提供的SSL安全通信机制来防止数据在网上被截获。

59ita点com(我就爱TA)
2005-09-19 23:53



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-28094-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.057700 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved