使用ADSI、ASP和一对魔术戏法自动地创立一个虚拟目录,第二部分
TomMoran和JeffSandquist
1999年2月22日
我们回来了。大家翘首以盼的这篇文章的第二部分现在在这儿。并且我想你将花费整个晚上看你的猫清洗自己。
这个月,JeffSandquist和我完成了我们的动态目录服务接口(ActiveDirectoryServicesInterfaces,ADSI)应用程序。如果你来晚了一点,没有问题;只要见这个系列的Part1http://www.microsoft.com/workshop/server/asp/server012599.asp。上个月,我们确认一个用户作为特权组的成员。接着我们显示了一个表单,表单上包括一个带有该特殊用户组中每个人用户名的列表框。这个表单允许我们选取一个用户,并且为这个用户的新的虚拟目录选择权限。现在我们将由这个表单获取数据并在网络服务器上创立一个新的虚拟目录,把它定义为一个应用,给出开启脚本权限的选项,并在文件夹上指定适当的权限。JeffSandquist将在这个过程中指导我们。
在这篇文章的结尾,我们有一个重要的、使人伤感的、足以使地球粉碎的公告。Clinton,O.J.,Clemens与之相比一切都显得苍白无力。我确信AP会注意到它,但是你将首先看到它。请继续阅读。
展览之中
上个月,我们的表格存在于一个叫Servin的虚拟目录。我们可以使用IUSR_<MachineName>中的InternetInformationServer(IIS)安全环境执行所请求的操作。我们需要一个管理员身份来创建目录和指定权限。
我们实现这个目的的一种方法是把IUSR_<MachineName>账号迁移到管理员组。而更好的方法是,在Web服务器上创建一个新的虚拟目录(我们将调用ServinSecure),并且把它设置成在管理员环境中操作,而不是在IUSR_<MachineName>环境中。我们的表单将保存在Servin目录中
而表单的处理器将保存在一个叫ServinSecure的目录中启动微软管理控制台(MicrosoftManagementConsole,MMC)然后用右键击DefaultWebSite创建一个新的虚拟目录。选择New/VirtualDirectory。创建一个叫"ServinSecure"(没有引号)的虚拟目录。你还需要提供一个以前在你的网络服务器文件系统中创建的文件夹的物理路径。一旦你创建了这个虚拟目录,用右键击中在MMC上新创建的虚拟目录,选择Properties显示虚拟目录的属性。
选择DirectorySecurity标签,选择Edit按钮,接着选择Enableanonymous…,编辑这个资源的身份确认方法。这时候会出现一个标题为AuthenticationMethods的对话框。选择Edit按钮,接着选择AccountusedforAnonymousAccess。出现一个题为AnonymousUserAccount的最终对话框。把用户名的缺省值从IUSR_<机器名>改成管理员,取消选定密码同步,并为管理员帐户提供密码。在剩余的每个对话框上选择OK使改变生效。
下面是对话框的图形:
ASP代码
让我们一起看一下代码。我们将为我们的应用程序定义一些变量。创立一个叫CreateDirectory.asp的动态服务器页(ActiveServerPages,ASP)文件,在其中插入以下代码:
<%@Language=VBScript%>
<%OptionExplicit%>
<HTML>
<HEAD>
<METANAME="GENERATOR"Content="MicrosoftVisualStudio6.0">
</HEAD>
<BODY>
<%
DimstrVirtualDirectoryName'IIS虚拟目录名
DimbolInProcessApplication'处理应用标记中的IIS
DimobjIIS'ADSIIIS对象
DimstrVirtualDirectoryPath'IIS虚拟目录路径
DimobjFileSystem'VBScript文件系统对象
DimstrOwner'NT文件夹所有者
DimobjVirtualDirectory'ADSIIIS虚拟目录对象
DimbolScriptPermissions'IIS脚本权限标记
DimstrHTTPReferer'IIS参考页
DimstrServerName'NT本地机器名
DimobjWSH'Windows脚本主机对象
DimobjRTC'返回
DimstrACLCommand'设置ACLs的命令行串
我们想确保用户是从我们的表单来的,并且没有欺骗我们的服务器。我们将检索HTTPReferer服务器变量和服务器名来测试它。这儿你可以做许多检查;在我们的测试中不必十分坚固。关于安全站点的优秀文章,请查看由DmitryKhanine整理的EasyApplicationStateSecurely(http://www.15seconds.com/Issue/990114.htm)。在代码的结尾插入以下代码:
strHTTPReferer=Request.ServerVariables("HTTP_REFERER")
strServerName=Request.ServerVariables("SERVER_NAME")
'我们是从我们的表格来的吗?如果不是,则拒绝存取
IfstrHTTPReferer<>"http://"&strServerName&"/Servin/Default.asp"then
Response.Write("AccessDenied")
Response.End
EndIf
现在我们的网页已证实我们的用户是从我们的表单传递结果的,我们可以获取虚拟目录(VirtualDirectory)、所有者(Owner)和脚本权限(ScriptPermissions)标记的值。请注意我们是怎样根据从checkboxScript获取的值来改变的,如果它被选定,就设为True,如果没有被选定就设为False。在你的最后一位代码后插入以下代码:
strVirtualDirectoryName=Request.Form("textVirtualDirectory")
strOwner=Request.Form("selectOwner")
IfRequest.Form("checkboxScript")="on"Then
bolScriptPermissions="True"
Else
bolScriptPermissions="False"
EndIf
我们需要确认IIS应用程序是否存在。使用IISAdmin对象,我们检查是否应用程序早已存在并且把相应的警告传递给用户。
'DoesthisIISapplicationalreadyexistinthemetabase?
OnErrorResumeNext
SetobjIIS=GetObject("IIS://localhost/W3SVC/1/Root/"&strVirtualDirectoryName)
IfErr.Number=0Then
Response.Write("Anapplicationwiththisnamealreadyexists.Click")
Response.Write("<AHREF=http://"&strServerName&"/servin/default.asp>")
Response.Write("here</A>tochooseadifferentname.")
Response.End
EndIf
SetobjIIS=Nothing
现在我们将使用IIS管理对象在meta数据库中创建IIS应用程序。
'创建IIS应用程序
SetobjIIS=GetObject("IIS://localhost/W3SVC/1/Root")
strVirtualDirectoryPath=objIIS.Path&""&strVirtualDirectoryName
使用VBScript的FileSystemObject对象,我们将测试文件夹是否存在于这个文件系统;如果不存在,我们将使用CreateFolder命令创建它。
SetobjFileSystem=Server.CreateObject("Scripting.FileSystemObject")
'Testtoseeifthefolderexistsinthefilesystem.Ifnot,createit
OnErrorResumeNext
SetFolder=objFileSystem.GetFolder(strVirtualDirectoryPath)
IfHex(Err.number)="4C"Then
objFileSystem.CreateFolderstrVirtualDirectoryPath
EndIf
SetobjFileSystem=Nothing
使用Administration对象(在这篇文章中我们多次使用),我们开启脚本权限(加入用户选择了这这选项)并定义虚拟目录作为一个进程中的应用。
'在文件系统上创建文件夹
SetobjVirtualDirectory=objIIS.Create("IISWebVirtualDir",strVirtualDirectoryName)
objVirtualDirectory.AccessScript=bolScriptPermissions
objVirtualDirectory.Path=strVirtualDirectoryPath
objVirtualDirectory.SetInfo
objVirtualDirectory.AppCreatebolInProcessApplication
现在看一下这个魔术:设置权限。我们确实认为这是很简单的部分。不幸地是,在ADSI中不存在能为虚拟目录设置权限的对象。惊慌失措,并且还有一点不舒服的感觉。(或者是由于昨天晚上大吃泰国饭菜引起的?)
搜索15seconds.com的ADSI列表服务器,发现一篇引用DOSCACLS.EXE文件的通讯(http://listserv.15seconds.com/scripts/wa15seconds.exe?A2=ind9806C&L=ADSI&P=R1861)并且通过DOSCMD文件使用它。我们认为我们可以为这个功能写一个VisualBasic封装并把它卷入一个定制组件(下个月的文章主题),但是一定有一个更快的方法。
我们在IanMorris整理的WindowsScriptingHostFAQ(http://wsh.glazier.co.nz/frame.htm)继续我们的搜索,发现了从WindowsScriptingHost?调用DOS命令的几行代码。
我们试图使用WindowsScriptinghost从ASP文件调用CACLS.exe,我们的网页不能执行。应用失败了。为什么会这样?我们从DOS命令提示单步调试这个命令发现CACLS.EXE命令在等待我们使用Y作为Yes来确认操作。一定有一种方法使Yes作为缺省值。
检查命令行选项没有发现任何隐藏开关。就这一点,打开浏览器,访问在线支持发现CACLS.EXE好象应该小心应用。
我们兴奋的发抖,发现了文章Q135268:HowtoUseCACLS.EXEinaBatchFile(http://support.microsoft.com/support/kb/articles/q135/2/68.asp)。啊哈,好的老DOS重定向。使用通道传输一个Y给CACLS.exe代表Yes。
下面是我们用来建立命令串和从ASP文件调用WindowsScriptingHostshell的代码。
'SetChangePermissionsforthedeveloperusingCACLS.exe
strACLCommand="cmd/cechoy|CACLS"
strACLCommand=strACLCommand&strVirtualDirectoryPath
strACLCommand=strACLCommand&"/g"&strOwner&":C"
SetobjWSH=Server.CreateObject("WScript.Shell")
objRTC=objWSH.Run(strACLCommand,0,True)
SetobjWSH=Nothing
这可能不是可伸缩性最好的解决方案。一个定制组件可以在大型的应用程序上更好的帮助你。如果你需要一个,Artisans软件有一个免费组件(http://www.softartisans.com/softartisans/safilemanager.html)允许你通过他的对象模型改变文件夹上的权限。(它也有一些其他很酷的特性,例如以点式输入/输出图像,操作.ini文件和更多。)
我们最终的代码证实我们所做的一切是值得的。
Response.Write("<B>WebApplicationCreatedSucessfully</B><BR>")
Response.Write("Path:"&strVirtualDirectoryPath&"<BR>")
Response.Write("ScriptPermissions:"&bolScriptPermissions&"<BR>")
Response.Write(strOwner&"hasbeengrantedchangepermissions<BR>")
%>
</BODY>
</HTML>
那就是它。当寻找问题的解答时最重要的使记住使用多种资源。列表服务器,FAQs和微软知识库就包含了这一类的文章。
现在是新闻由于我们在每一期ASP专栏中收到的热烈的反响,我们将把我们的栏目专门用于这种技术。可以预见的变化是,我们将介绍著名的JeffSandquist。那么有什么让人伤感的呢?TomMoran将离开Servin'ItUp--但是如果你将来在其他地方看到他时不要感到太惊奇。
JeffSandquist(微软最好的法裔加拿大人之一)是开发者支持的ActiveServerPages扩大组成员之一,也是VisualInterDevMVP程序(http://support.microsoft.com/support/supportnet/supportpartners/mvps/brochuregeneral.asp)的主要负责人。