ASP.NET网页设计保举:ASP.NET假造主机平安毛病办理计划...
我有个同学,他是搞Java的,他给我说“Java不是效率低,而是速度慢。”,我不是搞Java的,我实在想不透这句话的含义,难道执行速度不就是效率低吗?难道执行速度慢还成效率高了?asp.net|平安|平安毛病|办理|假造主机 申明:本文中所需情况为2003Server+iis6.0+mssql2000已经很早就在网上看到一篇关于<asp.net假造主机的严重隐患>的文章,事先其实不在乎,做过asp假造主机的伴侣大概都晓得,即对每个用户都设置一个自力的服务器用户和单个目次的操纵权限,可以基础上办理asp的fso成绩。
在网上偶然中发明了一个叫做webadmin的asp.net-webshell,对本人的服务器举行测试的时分,让我年夜吃一惊,竟然对我服务器的c盘有读取的权限。和对全部硬盘的修正删除权限。如许的话,那末我的服务器的平安……
为了进一步证明,自己曾在国际一些出名的假造主机供应商上作过测试,均有和我一样的成绩。
有需要先先容一下毛病的缘故原由。
ASP中经常使用的尺度组件:FileSystemObject,这个组件为ASP供应了壮大的文件体系会见才能,能够对服务器硬盘上的任何有权限的目次和文件举行读写、删除、更名等操纵。FSO工具来自微软供应的剧本运转库scrrun.dll中。
在ASP.NET中我们发明这一成绩仍旧存在,而且变得加倍难以办理。这是由于.NET中关于体系IO操纵的功效变得加倍壮大,而使这一成绩更严峻的是ASP.NET所具有的一项新功效,这就组件不必要象ASP那样必需要利用regsvr32来注册了,只需将Dll类库文件上传到bin目次下就能够间接利用了。这一功效的确给开辟ASP.NET带来了很年夜的便利,可是却使我们在ASP中将此dll删除大概更名的办理办法得到功效了,提防此成绩就变得加倍庞大。必要进一步懂得的伴侣能够看<asp.net假造主机的严重隐患>一文,本文就不再反复。只针对此成绩引出假造主机的平安设置。
网上提出针对此成绩用Microsoft.NETFrameworkConfigration设置System.io的对目次读取的权限,经由我们长工夫的测试没有乐成,多是.netframework1.1机制变革了?
空话不说。先说说办理的思绪:在IIS6中,Web使用程序的事情历程设置为以历程标识“NetworkService”运转。在IIS5中,历程外Web使用程序则设置为以IWAM_<服务器名>帐户运转,这个帐户是一般的当地用户帐户。
NetworkService是WindowsServer2003中的内置帐户。懂得IIS5上的当地用户帐户(IUSR和IWAM)与这个内置帐户之间的区分长短常主要的。Windows操纵体系中的一切帐户都分派了一个SID(平安标识,SecurityID)。服务器是依据SID,而不是与SID相干的称号来辨认服务器上一切帐户的,而我们在与用户界面举行交互时,则是利用称号举行交互的。服务器上创立的尽年夜部分帐户都是当地帐户,都具有一个独一的SID,用于标识此帐户从属于该服务器用户数据库的成员。因为SID只是相对服务器是独一的,因而它在任何其他体系上有效。以是,假如您为当地帐户分派了针对某文件或文件夹的NTFS权限,然后将该文件及其权限复制到另外一台盘算机上时,方针盘算机上并没有针对这个迁徙SID的用户帐户,即便其上有一个同名帐户也是云云。这使得包括NTFS权限的内容复制大概呈现成绩。
内置帐户是由操纵体系创立的、一类较为出格的帐户或组,比方System帐户、NetworkService和Everyone组。这些工具的主要特性之一就是,它们在一切体系上都具有一个不异的、尽人皆知的SID。当将分派了NTFS权限的文件复制到内置帐户时,权限在服务器之间是无效的,由于内置帐户的SID在一切服务器上都是不异的。WindowsServer2003服务中的NetworkService帐户是出格计划的,公用于为使用程序供应会见收集的充足权限,并且在IIS6中,无需提拔权限便可运转Web使用程序。这关于IIS平安性来讲,是一个特年夜的动静,由于不存在缓冲溢出,怀有歹意的使用程序没法破译历程标识,或是对使用程序的打击不克不及进进System用户情况。更加主要的一点是,不再能构成针对System帐户的“后门”,比方,再也没法经由过程InProcessIsapiApps元数据库项使用加载到Inetinfo的使用程序。
NetworkService帐户在创立时不单单思索了在IIS6中的使用。它还具有历程标识W3WP.exe的尽年夜部分(并非全体)权限。好像ASPNET用户为了运转ASP.net使用程序,必要具有IIS5服务器上某些地位的会见权限,历程标识W3WP.exe也必要具有相似地位的会见权限,并且还必要一些默许情形下没有指派给内置组的权限。
为了办理的便利,在安装IIS6时创立了IIS_WPG组(也称为IIS事情历程组,IISWorkerProcessGroup),并且它的成员包含LocalSystem(当地体系)、LocalService(当地服务)、NetworkService(收集服务)和IWAM帐户。IIS_WPG的成员具有得当的NTFS权限和需要的用户权限,能够充任IIS6中事情历程的历程标识。
因而,NetworkService帐户供应了会见上述地位的权限,具有充任IIS6事情历程的历程标识的充分权限,和具有会见收集的权限。
Msdn上说:在WindowsServer2003中,用户高低文称为NETWORKSERVICE。这些用户帐户是在.NETFramework安装过程当中创立的,它具有独一的不容易破解的暗码,并仅被授与无限的权限。ASPNET或NETWORKSERVICE用户只能会见运转Web使用程序所需的特定文件夹,如Web使用程序存储已编译文件的in目次。
要将历程标识设置为特定用户名,以代替ASPNET或NETWORKSERVICE用户标识,您供应的用户名和暗码都必需存储在machine.config文件中。
可是依据实践情形,asp.net的system.io能够无穷制会见不设防的服务器路径。不晓得这算不算一个ms的严重毛病。并且基本不克不及使iis以machine.config的用户实行asp.net程序。J
怎样办理呢?谜底就是―使用程序池。
IIS6.0在被称为使用程序断绝形式(断绝形式)的两种分歧操纵形式下运转,它们是:事情历程断绝形式和IIS5.0断绝形式。这两种形式都要依附于HTTP.sys作为超文本传输协定(HTTP)侦听程序;但是,它们外部的事情道理是一模一样的。
事情历程断绝形式使用IIS6.0的从头计划的系统布局而且利用事情历程的中心组件。IIS5.0断绝形式用于依附IIS5.0的特定功效和举动的使用程序。该断绝形式由IIs5IsolationModeEnabled设置数据库属性指定。
您所选择的IIS使用程序断绝形式对功能、牢靠性、平安性和功效可用性城市发生影响。事情历程断绝形式是IIS6.0操纵的保举形式,由于它为使用程序供应了更牢靠的平台。事情历程断绝形式也供应了更初级其余平安性,由于运转在事情历程中的使用程序的默许标识为NetworkService。
以IIS5.0断绝形式运转的使用程序的默许标识为LocalSystem,该标识同意会见并具有变动盘算机上几近一切资本的才能。
IIS功效IIS5.0断绝形式宿主/组件事情历程断绝形式宿主/组件事情历程办理N/ASvchost.exe/WWW服务事情历程N/AW3wp.exe/事情历程运转历程内ISAPI扩大Inetinfo.exeW3wp.exe运转历程外ISAPI扩大DLLHost.exeN/A(一切的ISAPI扩大都在历程内)运转ISAPI选择器Inetinfo.exeW3wp.exeHTTP.sys设置Svchost.exe/WWW服务Svchost.exe/WWW服务HTTP协定撑持Windows内核/HTTP.sysWindows内核/HTTP.sysIIS设置数据库Inetinfo.exeInetinfo.exeFTPInetinfo.exeInetinfo.exeNNTPInetinfo.exeInetinfo.exeSMTPInetinfo.exeInetinfo.exe
因而可知,我们只能利用事情历程断绝形式办理.net的平安成绩。
<P> 默许情形下,IIS6.0在事情历程断绝形式下运转,如图五所示。在这类形式中,关于每个Web使用,IIS6.0都用一个自力的w3wp.exe的实例来运转它。w3wp.exe也称为事情历程(WorkerProcess),或W3Core。
牢靠性和平安性。牢靠性的进步是由于一个Web使用的妨碍不会影响到其他Web使用,也不会影响http.sys,每个Web使用由W3SVC独自地监督其安康情况。平安性的进步是因为使用程序不再象IIS5.0和IIS4.0的历程内使用那样用System帐户运转,默许情形下,w3wp.exe的一切实例都在一个权限无限的“收集服务”帐户下运转,如图六所示,需要时,还能够将事情历程设置成用其他用户帐户运转。
对,这里,这里就是我们办理的中心。
我们把每个网站都分派一个自力的使用程序池,并付与分歧的权限。不就可以办理这个成绩了吗?
详细怎样做呢,上面我就针对创建一个网站来做一个树模:
起首,我们为网站创立两个用户(一个是app_test_user、暗码为appuser,一个是iis_test_user、暗码为iisuser)
1.翻开盘算机办理器
2.单击把持台树中的用户→盘算机办理→体系工具→当地用户和组→用户
3.单击“操纵”菜单上的“新用户”输出用户名为。app_test_user、暗码为appuser
4.在对话框中键进得当的信息。
5.选中复选框:
用户不克不及变动暗码
暗码永不外期
6.单击“创立”,然后单击“封闭”。
依照此办法在创立iis_test_user账户
然后分离把app_test_user增加到iis_wpg组,把iis_test_user增加到Guests组。删除其他组。
然后,创建响应的使用程序池。
顺次翻开Internet信息服务→当地盘算机→使用程序池→新建→使用程序池
新建一个名字为test的使用程序池
编纂test使用程序池的属性→标示→设置→用户名→扫瞄→把用户名改成我们方才创建的app_test_user并输出响应的暗码
其次创建响应的网站。
顺次翻开Internet信息服务→当地盘算机→网站→新建→test的网站,目次为d: est→编纂test网站的属性→主目次→使用程序池→app_test_user→目次平安性→身份考证和会见把持→编纂,选择我们方才创建的iis_test_user,并输出响应的暗码iisuser→保留并加入。
最初设定服务器的平安。
C:只给administrators和system完整把持的权力,删撤除其他一切的权限,不交换子目次
C:DocumentsandSettings承继父项,并交换子目次。
C:ProgramFiles承继父项,并交换子目次,并把C:ProgramFilesCommonFilesMicrosoftShared承继属性删除并复制现有属性,增添users的读取权限并交换子目次(如许做是为了可以让asp,asp.net利用access等数据库)。
C:windows删除承继,并复制现有属性,只赐与administrators,system完整把持和users读取的权限并交换子目次。
其他一切的盘都只给于administrators和system用户的完整把持权限,删除其他一切用户并交换子目次。
D: est(用户网站目次)承继现有属性并增添app_test_user和iis_test_user完整把持的权限并交换子目次。
今后每增添一个网站都以此类推。
可是,至此,system.io仍是对c:windows又读取权限的,(嫌疑networkservers用户属于users组,可是很多多少服务都要利用users组来实行的,以是不克不及把c:windwos往失落users组的读取权限)但必需晓得体系路径,有两种计划办理。
1、再安装体系的时分利用无人值守安装,改换c:windows默许安装路径,如变动为c: esttest(要切合dos的定名划定规矩,不克不及凌驾8个字符)。这个是必须的
2、以下地位具有指派给IIS_WPG的权限:
%windir%helpiishelpcommonC读取
%windir%IISTemporaryCompressedFilesC列出、读取、写进
%windir%system32inetsrvASPCompiledTemplateC读取
Inetpubwwwroot(或内容目次)-读取、实行
别的,IIS_WPG还具有以下用户权限:
疏忽遍历反省(SeChangeNotifyPrivilege)
作为批处置功课登录(SeBatchLogonRight)
从收集会见此盘算机(SeNetworkLogonRight)
固然两种办法分离起来算是最平安的计划,一样平常利用第一种计划已算是很平安的,究竟是用一个webshell来推测8位字符的目次仍是必要消费工夫的。利用防火墙很简单就可以发觉出来,并加以把持。
第二种大概依据所安装软件分歧还要响应增添目次的读取权限,具体情形要依据软件来断定。
假如主机用户对照多,这将是一个相称年夜的休息量,保举利用程序来办理成绩,上面给出网上不罕见的针对iis使用程序池操纵的代码和针对iis假造目次的操纵代码。
操纵iis使用程序池
usingSystem;
usingSystem.DirectoryServices;
usingSystem.Reflection;
namespaceADSI1
{
///
///SmallclasscontainingmethodstoconfigureIIS.
///
classConfigIIS
{
///
///Themainentrypointfortheapplication.
///
//主程序出口,能够选择用哪些,我为了便利,全体功效都写上往了。
staticvoidMain(string[]args)
{
stringAppPoolName="MyAppPool";
stringnewvdir1="MyVDir";
DirectoryEntrynewvdir=CreateVDir(newvdir1);
CreateAppPool(AppPoolName);
AssignAppPool(newvdir,AppPoolName);
ConfigAppPool("Stop",AppPoolName);
}
//创立假造目次
staticDirectoryEntryCreateVDir(stringvdirname)
{
DirectoryEntrynewvdir;
DirectoryEntryroot=newDirectoryEntry("IIS://localhost/W3SVC/1/Root");
newvdir=root.Children.Add(vdirname,"IIsWebVirtualDir");
newvdir.Properties["Path"]="c:inetpubwwwroot";
newvdir.Properties["AccessScript"]=true;
newvdir.CommitChanges();
returnnewvdir;
}
//创立新的使用程序池。
staticvoidCreateAppPool(stringAppPoolName)
{
DirectoryEntrynewpool;
DirectoryEntryapppools=newDirectoryEntry("IIS://localhost/W3SVC/AppPools");
newpool=apppools.Children.Add(AppPoolName,"IIsApplicationPool");
newpool.CommitChanges();
}
staticvoidAssignAppPool(DirectoryEntrynewvdir,stringAppPoolName)
{
object[]param={0,AppPoolName,true};
newvdir.Invoke("AppCreate3",param);
}
//method是办理使用程序池的办法,有三种Start、Stop、Recycle,而AppPoolName是使用程序池称号
staticvoidConfigAppPool(stringmethod,stringAppPoolName)
{
DirectoryEntryappPool=newDirectoryEntry("IIS://localhost/W3SVC/AppPools");
DirectoryEntryfindPool=appPool.Children.Find(AppPoolName,IIsApplicationPool");
findPool.Invoke(method,null);
appPool.CommitChanges();
appPool.Close();
}
//使用程序池的列表
staticvoidAppPoolList()
{
DirectoryEntryappPool=newDirectoryEntry("IIS://localhost/W3SVC/AppPools");
foreach(DirectoryEntryainappPool.Children)
{
Console.WriteLine(a.Name);
}
}
privatevoidVDirToAppPool()
{
DirectroryEntryVD=newDirectoryEntry("IIS://localhost/W3SVC/1/ROOT/ccc");
Console.WriteLine(VD.Properties["AppPoolId"].Value.ToString());
}
}
}
iis6操纵的例子
usingSystem;
usingSystem.DirectoryServices;
usingSystem.Collections;
usingSystem.Text.RegularExpressions;
usingSystem.Text;
namespaceWuhy.ToolBox
{
///</summary>
publicclassIISAdminLib
{
#regionUserName,Password,HostName的界说
publicstaticstringHostName
{
get
{
returnhostName;
}
set
{
hostName=value;
}
}
publicstaticstringUserName
{
get
{
returnuserName;
}
set
{
userName=value;
}
}
publicstaticstringPassword
{
get
{
returnpassword;
}
set
{
if(UserName.Length<=1)
{
thrownewArgumentException("还没有指定好用户名。请先指定用户名");
}
password=value;
}
}
publicstaticvoidRemoteConfig(stringhostName,stringuserName,stringpassword)
{
HostName=hostName;
UserName=userName;
Password=password;
}
privatestaticstringhostName="localhost";
privatestaticstringuserName;
privatestaticstringpassword;
#endregion
#region依据路径机关Entry的办法
///<summary>
///依据是不是有效户名来判别是不是是远程服务器。
///然后再机关出分歧的DirectoryEntry出来
///</summary>
///<paramname="entPath">DirectoryEntry的路径</param>
///<returns>前往的是DirectoryEntry实例</returns>
publicstaticDirectoryEntryGetDirectoryEntry(stringentPath)
{
DirectoryEntryent;
if(UserName==null)
{
ent=newDirectoryEntry(entPath);
}
else
{
//ent=newDirectoryEntry(entPath,HostName+""+UserName,Password,AuthenticationTypes.Secure);
ent=newDirectoryEntry(entPath,UserName,Password,AuthenticationTypes.Secure);
}
returnent;
}
#endregion
#region增加,删除网站的办法
///<summary>
///创立一个新的网站。依据传过去的信息举行设置
///</summary>
///<paramname="siteInfo">存储的是新网站的信息</param>
publicstaticvoidCreateNewWebSite(NewWebSiteInfositeInfo)
{
if(!EnsureNewSiteEnavaible(siteInfo.BindString))
{
thrownewDuplicatedWebSiteException("已有了如许的网站了。"+Environment.NewLine+siteInfo.BindString);
}
stringentPath=String.Format("IIS://{0}/w3svc",HostName);
DirectoryEntryrootEntry=GetDirectoryEntry(entPath);
stringnewSiteNum=GetNewWebSiteID();
DirectoryEntrynewSiteEntry=rootEntry.Children.Add(newSiteNum,"IIsWebServer");
newSiteEntry.CommitChanges();
newSiteEntry.Properties["ServerBindings"].Value=siteInfo.BindString;
newSiteEntry.Properties["ServerComment"].Value=siteInfo.CommentOfWebSite;
newSiteEntry.CommitChanges();
DirectoryEntryvdEntry=newSiteEntry.Children.Add("root","IIsWebVirtualDir");
vdEntry.CommitChanges();
vdEntry.Properties["Path"].Value=siteInfo.WebPath;
vdEntry.CommitChanges();
}
///<summary>
///删除一个网站。依据网站称号删除。
///</summary>
///<paramname="siteName">网站称号</param>
publicstaticvoidDeleteWebSiteByName(stringsiteName)
{
stringsiteNum=GetWebSiteNum(siteName);
stringsiteEntPath=String.Format("IIS://{0}/w3svc/{1}",HostName,siteNum);
DirectoryEntrysiteEntry=GetDirectoryEntry(siteEntPath);
stringrootPath=String.Format("IIS://{0}/w3svc",HostName);
DirectoryEntryrootEntry=GetDirectoryEntry(rootPath);
rootEntry.Children.Remove(siteEntry);
rootEntry.CommitChanges();
}
#endregion
#regionStart和Stop网站的办法
publicstaticvoidStartWebSite(stringsiteName)
{
stringsiteNum=GetWebSiteNum(siteName);
stringsiteEntPath=String.Format("IIS://{0}/w3svc/{1}",HostName,siteNum);
DirectoryEntrysiteEntry=GetDirectoryEntry(siteEntPath);
siteEntry.Invoke("Start",newobject[]{});
}
publicstaticvoidStopWebSite(stringsiteName)
{
stringsiteNum=GetWebSiteNum(siteName);
stringsiteEntPath=String.Format("IIS://{0}/w3svc/{1}",HostName,siteNum);
DirectoryEntrysiteEntry=GetDirectoryEntry(siteEntPath);
siteEntry.Invoke("Stop",newobject[]{});
}
#endregion
#region确认网站是不是不异
///<summary>
///断定一个新的网站与现有的网站没有不异的。
///如许避免将不法的数据寄存到IIS内里往
///</summary>
///<paramname="bindStr">网站邦定信息</param>
///<returns>真为能够创立,假为不成以创立</returns>
publicstaticboolEnsureNewSiteEnavaible(stringbindStr)
{
stringentPath=String.Format("IIS://{0}/w3svc",HostName);
DirectoryEntryent=GetDirectoryEntry(entPath);
foreach(DirectoryEntrychildinent.Children)
{
if(child.SchemaClassName=="IIsWebServer")
{
if(child.Properties["ServerBindings"].Value!=null)
{
if(child.Properties["ServerBindings"].Value.ToString()==bindStr)
{
returnfalse;
}
}
}
}
returntrue;
}
#endregion
#region猎取一个网站编号的办法
///<summary>
///猎取一个网站的编号。依据网站的ServerBindings大概ServerComment来断定网站编号
///</summary>
///<paramname="siteName"></param>
///<returns>前往网站的编号</returns>
///<exceptioncref="NotFoundWebSiteException">暗示没有找到网站</exception>
publicstaticstringGetWebSiteNum(stringsiteName)
{
Regexregex=newRegex(siteName);
stringtmpStr;
stringentPath=String.Format("IIS://{0}/w3svc",HostName);
DirectoryEntryent=GetDirectoryEntry(entPath);
foreach(DirectoryEntrychildinent.Children)
{
if(child.SchemaClassName=="IIsWebServer")
{
if(child.Properties["ServerBindings"].Value!=null)
{
tmpStr=child.Properties["ServerBindings"].Value.ToString();
if(regex.Match(tmpStr).Success)
{
returnchild.Name;
}
}
if(child.Properties["ServerComment"].Value!=null)
{
tmpStr=child.Properties["ServerComment"].Value.ToString();
if(regex.Match(tmpStr).Success)
{
returnchild.Name;
}
}
}
}
thrownewNotFoundWebSiteException("没有找到我们想要的站点"+siteName);
}
#endregion
#region猎取新网站id的办法
///<summary>
///猎取网站体系内里可使用的最小的ID。
///这是由于每一个网站都必要有一个独一的编号,并且这个编号越小越好。
///这内里的算法经由了测试是没有成绩的。
///</summary>
///<returns>最小的id</returns>
publicstaticstringGetNewWebSiteID()
{
ArrayListlist=newArrayList();
stringtmpStr;
stringentPath=String.Format("IIS://{0}/w3svc",HostName);
DirectoryEntryent=GetDirectoryEntry(entPath);
foreach(DirectoryEntrychildinent.Children)
{
if(child.SchemaClassName=="IIsWebServer")
{
tmpStr=child.Name.ToString();
list.Add(Convert.ToInt32(tmpStr));
}
}
list.Sort();
inti=1;
foreach(intjinlist)
{
if(i==j)
{
i++;
}
}
returni.ToString();
}
#endregion
}
#region新网站信息布局体
publicstructNewWebSiteInfo
{
privatestringhostIP;//TheHostsIPAddress
privatestringportNum;//TheNewWebSitesPort.generallyis"80"
privatestringdescOfWebSite;//网站暗示。通常是网站的网站名。比方"www.dns.com.cn"
privatestringcommentOfWebSite;//网站正文。一样平常也为网站的网站名。
privatestringwebPath;//网站的主目次。比方"e: mp"
publicNewWebSiteInfo(stringhostIP,stringportNum,stringdescOfWebSite,stringcommentOfWebSite,stringwebPath)
{
this.hostIP=hostIP;
this.portNum=portNum;
this.descOfWebSite=descOfWebSite;
this.commentOfWebSite=commentOfWebSite;
this.webPath=webPath;
}
publicstringBindString
{
get
{
returnString.Format("{0}:{1}:{2}",hostIP,portNum,descOfWebSite);
}
}
publicstringCommentOfWebSite
{
get
{
returncommentOfWebSite;
}
}
publicstringWebPath
{
get
{
returnwebPath;
}
}
}
#endregion
}
至此,一个绝对平安的.net主机就创建起来了,跟着.net2.0的公布愈来愈切近亲近,但愿ms能针对此成绩作一个妥帖的提防。
我们已复杂的先容了一下ASP.NET中关于文件IO体系的毛病的防治办法,这一办法有些烦琐,可是却能够从基本上根绝一些毛病,我们会商的只是很少的一部分,更多的办理放法必要人人配合来探究、进修。以前很热炒跨平台,主要是由于硅谷挑战微软霸主地位的热情,但是冷静下来后,跨平台往往不是那么一回事。假设你有个软件,所谓的跨平台,你只需要为第二个平台上重新编译一次就行了,这样很难么? 弱类型造成潜在的出错可能:尽管弱数据类型的编程语言使用起来回方便一些,但相对于它所造成的出错几率是远远得不偿失的。 主流网站开发语言之CGI:CGI就是公共网关接口(CommonGatewayInterface)的缩写。它是最早被用来建立动态网站的后台技术。这种技术可以使用各种语言来编写后台程序,例如C,C++,Java,Pascal等。 ASP.Net摆脱了以前ASP使用脚本语言来编程的缺点,理论上可以使用任何编程语言包括C++,VB,JS等等,当然,最合适的编程语言还是MS为.NetFrmaework专门推出的C(读csharp)。 有一丝可惜的是,这个系列太强了,Java阵营的朋友根本就是哑口无言...争论之火瞬间被浇灭,这不是我想这么早就看到的,但是值了。 主流网站开发语言之CGI:CGI就是公共网关接口(CommonGatewayInterface)的缩写。它是最早被用来建立动态网站的后台技术。这种技术可以使用各种语言来编写后台程序,例如C,C++,Java,Pascal等。 是目前ASP在UNIX/Linux上的应用可以说几乎为0)。所以平台的局限性和ASP自身的安全性限制了ASP的广泛应用。 最强的技术支持WebService,而且有.NET的所有library做后盾。而且ASP.NET在.NET3.5中还有微软专门为AJAX开发的功能--ASP.NETAJAX。
页:
[1]