Jun
23
该段代码涉及到JMail v4.5的大部分常用方法。包括邮件基本信息、身份验证、附件等。无需很多的修改就可以使用,也可以改成函数或过程。
<%
Dim JMail, contentId
Set JMail = Server.CreateObject("JMail.Message")
JMail.Charset = "gb2312" ' 邮件字符集,默认为"US-ASCII"
' JMail.ISOEncodeHeaders = False ' 是否进行ISO编码,默认为True
' 发送者信息(可用变量方式赋值)
JMail.From = "[email protected]" ' 发送者地址
JMail.FromName = "D.J." ' 发送者姓名
JMail.Subject = "您在炫网资讯的歌词快递(请将编码设为简体中文(gb2312))" ' 邮件主题
' 身份验证
JMail.MailServerUserName = "user" ' 身份验证的用户名
JMail.MailServerPassword = "password" ' 身份验证的密码
' 设置优先级,范围从1到5,越大的优先级越高,3为普通
JMail.Priority = 3
JMail.AddHeader "Originating-IP", Request.ServerVariables("REMOTE_ADDR")
' 加入一个收件人【变量email:收件人地址】可以同一语句重复加入多个
JMail.AddRecipient(email)
' 加入附件【变量filename:附件文件的绝对地址,确保用户IUSR_????有访问的权限】
' 【参数设置是(True)否(False)为Inline方式】
contentId = JMail.AddAttachment (filename, True)
' 邮件主体(HTML(注意信件内链接附件的方式))
JMail.HTMLBody = "<html><head><META content=zh-cn http-equiv=Content-Language><meta http-equiv=""Content-Type"" content=""text/html; charset=gb2312""><style type=text/css>A:link { FONT-SIZE: 9pt; TEXT-DECORATION: none; color: #000000}A:visited {FONT-SIZE: 9pt; TEXT-DECORATION: none; color: #666666}A:hover {COLOR: #ff6600; FONT-SIZE: 9pt; TEXT-DECORATION: underline}BODY {FONT-SIZE: 9pt} --></style></head><body bgcolor=""#FFFFFF"" text=""#666666"" leftmargin=""0"" topmargin=""30"" link=""#FF9900""><center>点击这里<a href=' cid:" & contentId & "' >[附件文件]</a>将文件保存</center></body></html>"
' 邮件主体(文本部分)
JMail.Body = "我们的邮件采用了HTML格式,但是您的邮件查看软件可能不支持。您可以访问以下地址来查看:http://music.liuxuan.com"
' 发送【调用格式:objJMail.Send([username:password@]SMTPServerAddress[:Port])】
JMail.Send("user:[email protected]")
' 关闭并清除对象
JMail.Close()
Set JMail = Nothing
%>
<%
Dim JMail, contentId
Set JMail = Server.CreateObject("JMail.Message")
JMail.Charset = "gb2312" ' 邮件字符集,默认为"US-ASCII"
' JMail.ISOEncodeHeaders = False ' 是否进行ISO编码,默认为True
' 发送者信息(可用变量方式赋值)
JMail.From = "[email protected]" ' 发送者地址
JMail.FromName = "D.J." ' 发送者姓名
JMail.Subject = "您在炫网资讯的歌词快递(请将编码设为简体中文(gb2312))" ' 邮件主题
' 身份验证
JMail.MailServerUserName = "user" ' 身份验证的用户名
JMail.MailServerPassword = "password" ' 身份验证的密码
' 设置优先级,范围从1到5,越大的优先级越高,3为普通
JMail.Priority = 3
JMail.AddHeader "Originating-IP", Request.ServerVariables("REMOTE_ADDR")
' 加入一个收件人【变量email:收件人地址】可以同一语句重复加入多个
JMail.AddRecipient(email)
' 加入附件【变量filename:附件文件的绝对地址,确保用户IUSR_????有访问的权限】
' 【参数设置是(True)否(False)为Inline方式】
contentId = JMail.AddAttachment (filename, True)
' 邮件主体(HTML(注意信件内链接附件的方式))
JMail.HTMLBody = "<html><head><META content=zh-cn http-equiv=Content-Language><meta http-equiv=""Content-Type"" content=""text/html; charset=gb2312""><style type=text/css>A:link { FONT-SIZE: 9pt; TEXT-DECORATION: none; color: #000000}A:visited {FONT-SIZE: 9pt; TEXT-DECORATION: none; color: #666666}A:hover {COLOR: #ff6600; FONT-SIZE: 9pt; TEXT-DECORATION: underline}BODY {FONT-SIZE: 9pt} --></style></head><body bgcolor=""#FFFFFF"" text=""#666666"" leftmargin=""0"" topmargin=""30"" link=""#FF9900""><center>点击这里<a href=' cid:" & contentId & "' >[附件文件]</a>将文件保存</center></body></html>"
' 邮件主体(文本部分)
JMail.Body = "我们的邮件采用了HTML格式,但是您的邮件查看软件可能不支持。您可以访问以下地址来查看:http://music.liuxuan.com"
' 发送【调用格式:objJMail.Send([username:password@]SMTPServerAddress[:Port])】
JMail.Send("user:[email protected]")
' 关闭并清除对象
JMail.Close()
Set JMail = Nothing
%>
Jun
23
导言
改善程序性能是一件很微妙的事情。尤其是和INTERNET相关的程序,像ASP程序,制约其性能的因素很多,像WEB服务器、TCP/IP网络和数据库服务器等。这些大都是与硬件相关。其实在软件上,好的程序设计的方法和正确的参数配置也可以提高程序的性能,有时在同等情况下只要改变一个参数,程序执行效率就能大大提高。本文就试着在这方面做些探索。
一.影响性能的因素
ASP程序运行的性能主要决定于以下2个大方面:
1.HTML页面的执行效率
2.反应时间,其中反应时间主要受制于下面要素:
(1).ASP页面的执行效率
(2).数据库因素
下面我们就来详细讨论一下。
二.详细讨论
1.影响HTML的因素
HTML页面的执行效率是一个纯客户端的问题。影响这个问题的因素主要是客户端的硬件和他的网络带宽。除此之外,还有些下列因素也可以影响HTML页面的执行效率。
(1).图象因素。在HTML的页面尽量避免使用图象。这是因为当浏览器请求一个页面时,如果页面包含N个图象,这将使的浏览器要向WEB服务器请求N次调用。而这种请求会降低页面的加载进程。进而影响速度。
(2).框架问题。在网页里面使用框架同样也会降低页面的加载进程,和图象因素相似,加载一个N个框架也需要请求N次。
(3).表格问题,尽量避免使用表格,尤其是尽量避免使用多重表格,繁杂的表格会影响HTML的执行效率。
(4).去除多余的标记符,让我们来看看下面的例子:
<Body><br>
<P><font face="Verdana" size="4"><br>
</font></P><br>
<P><font face="Verdana" size="4"><br>
</font></P><br>
<P><font face="Verdana" size="4"><br>
</font></P><br>
</Body><br>
你可以去掉 <font>标记符,如下:
<Body><br>
<font face="Verdana" size="4"><br>
<P><br>
</P> <br>
<P> <br>
</P><br>
<P> <br>
</P><br>
<font> </Body><br>
(5).减少注释,这将会减少文件的大小。进而提高加载速度。
(6).避免使用长文件名,并且在页面里尽量使用相对路径访问其他文件。
(7).在HTML页面里面尽量避免使用Java Applets。例如,如果你想使用Java Applets来处理动画,那么你可以考虑用GIF文件或者是FLASH来代替,而这将比Java Applets快很多。
2.影响ASP的要素
(1).尽量把对象变量转换成本地变量,因为读本地变量比读对象变量要快许多。
比较慢的例子:
if Myobj.Value = 0 then
Do something
elseif Myobj.Value > 0 then
Do something
elseif Myobj.Value < 0 then
Do something
end if
比较快的例子:
MyVar = Myobj.Value
if MyVar = 0 then
Do something
elseif MyVar > 0 then
Do something
elseif MyVar < 0 then
Do something
end if
(2).如果你使用的是VBScript 5.0或者是更新的版本,尽量使用 With ... End With语句,这也可以提高你的程序运行速度。
比较慢的例子:
Myobj.FirstName = "Srinivasa"
Myobj.LastName = "Sivakumar"
Myobj.City = "Chicago"
比较快的例子:
With Myobj
.FirstName = "金虎"
.LastName = "马"
.City = "滁州"
End with
(3).就总体而言,避免使用session变量有助于提高速度,这是因为不同的ASP页面分别在不同的线程里面运行的,而session调用却不是这样的,他是连续的。
3.数据库问题
设计好一个数据库结构可以大大提高程序的运行速度,当然怎么设计数据库结构不是本文讨论的问题。我们先假设已经设计好了数据库结构,看看还能做些什么事情来提高程序的运行速度。
(1).如果你的数据库服务器和WEB服务器是同一个,那么最好分开。这肯定能够提高速度。
(2).如果你访问数据库,最好不要使用动态的SQL语句,使用存储过程或者视图。
(3).有时分配适当的数据库buffers会提高程序的性能。这是因为,假如如果你使用的是Oracle数据库,对于每个连接都需要打开三个sessions。如果你能够处理好这些事情,你将会提高程序的性能。
总结
其实影响ASP程序执行速度的因素有很多,以上只是一部分。当然上面的一些技巧也不一定适合所有的ASP程序,对待不同的程序要采用不同的策略。最后希望以上的本文能对您有所帮助。
改善程序性能是一件很微妙的事情。尤其是和INTERNET相关的程序,像ASP程序,制约其性能的因素很多,像WEB服务器、TCP/IP网络和数据库服务器等。这些大都是与硬件相关。其实在软件上,好的程序设计的方法和正确的参数配置也可以提高程序的性能,有时在同等情况下只要改变一个参数,程序执行效率就能大大提高。本文就试着在这方面做些探索。
一.影响性能的因素
ASP程序运行的性能主要决定于以下2个大方面:
1.HTML页面的执行效率
2.反应时间,其中反应时间主要受制于下面要素:
(1).ASP页面的执行效率
(2).数据库因素
下面我们就来详细讨论一下。
二.详细讨论
1.影响HTML的因素
HTML页面的执行效率是一个纯客户端的问题。影响这个问题的因素主要是客户端的硬件和他的网络带宽。除此之外,还有些下列因素也可以影响HTML页面的执行效率。
(1).图象因素。在HTML的页面尽量避免使用图象。这是因为当浏览器请求一个页面时,如果页面包含N个图象,这将使的浏览器要向WEB服务器请求N次调用。而这种请求会降低页面的加载进程。进而影响速度。
(2).框架问题。在网页里面使用框架同样也会降低页面的加载进程,和图象因素相似,加载一个N个框架也需要请求N次。
(3).表格问题,尽量避免使用表格,尤其是尽量避免使用多重表格,繁杂的表格会影响HTML的执行效率。
(4).去除多余的标记符,让我们来看看下面的例子:
<Body><br>
<P><font face="Verdana" size="4"><br>
</font></P><br>
<P><font face="Verdana" size="4"><br>
</font></P><br>
<P><font face="Verdana" size="4"><br>
</font></P><br>
</Body><br>
你可以去掉 <font>标记符,如下:
<Body><br>
<font face="Verdana" size="4"><br>
<P><br>
</P> <br>
<P> <br>
</P><br>
<P> <br>
</P><br>
<font> </Body><br>
(5).减少注释,这将会减少文件的大小。进而提高加载速度。
(6).避免使用长文件名,并且在页面里尽量使用相对路径访问其他文件。
(7).在HTML页面里面尽量避免使用Java Applets。例如,如果你想使用Java Applets来处理动画,那么你可以考虑用GIF文件或者是FLASH来代替,而这将比Java Applets快很多。
2.影响ASP的要素
(1).尽量把对象变量转换成本地变量,因为读本地变量比读对象变量要快许多。
比较慢的例子:
if Myobj.Value = 0 then
Do something
elseif Myobj.Value > 0 then
Do something
elseif Myobj.Value < 0 then
Do something
end if
比较快的例子:
MyVar = Myobj.Value
if MyVar = 0 then
Do something
elseif MyVar > 0 then
Do something
elseif MyVar < 0 then
Do something
end if
(2).如果你使用的是VBScript 5.0或者是更新的版本,尽量使用 With ... End With语句,这也可以提高你的程序运行速度。
比较慢的例子:
Myobj.FirstName = "Srinivasa"
Myobj.LastName = "Sivakumar"
Myobj.City = "Chicago"
比较快的例子:
With Myobj
.FirstName = "金虎"
.LastName = "马"
.City = "滁州"
End with
(3).就总体而言,避免使用session变量有助于提高速度,这是因为不同的ASP页面分别在不同的线程里面运行的,而session调用却不是这样的,他是连续的。
3.数据库问题
设计好一个数据库结构可以大大提高程序的运行速度,当然怎么设计数据库结构不是本文讨论的问题。我们先假设已经设计好了数据库结构,看看还能做些什么事情来提高程序的运行速度。
(1).如果你的数据库服务器和WEB服务器是同一个,那么最好分开。这肯定能够提高速度。
(2).如果你访问数据库,最好不要使用动态的SQL语句,使用存储过程或者视图。
(3).有时分配适当的数据库buffers会提高程序的性能。这是因为,假如如果你使用的是Oracle数据库,对于每个连接都需要打开三个sessions。如果你能够处理好这些事情,你将会提高程序的性能。
总结
其实影响ASP程序执行速度的因素有很多,以上只是一部分。当然上面的一些技巧也不一定适合所有的ASP程序,对待不同的程序要采用不同的策略。最后希望以上的本文能对您有所帮助。
Jun
1
记录并显示网页的最后修改时间
<script language=JavaScript>
document.write("最后更新时间: " + document.lastModified + "")
</script>
2秒后关闭当前页
<script language="JavaScript">
<!--
setTimeout(''window.close();'',2000);
-->
</script>
2秒后载入指定网页
<head>
<meta http-equiv="refresh" content="2;URL=http://你的网址">
</head>
添加到收藏夹
<Script Language="JavaScript">
function bookmarkit()
{
window.external.addFavorite(''http://你的网址'',''你的网站名称'')
}
if (document.all)document.write(''<a href="#" onClick="bookmarkit()">加入收藏夹</a>'')
</Script>
禁止鼠标右键的动作
<Script Language = "JavaScript">
function click() { if (event.button==2||event.button==3)
{
alert(''禁止鼠标右键'');
}
document.onmousedown=click // -->
</Script>
或
<script language="JavaScript">
function click() { if (event.button==2)
{alert(''*^_^*''); } } document.onmousedown=click // -->
</script>
设置该页为首页
<body bgcolor="#FFFFFF" text="#000000">
<a class="chlnk" style="cursor:hand" HREF onClick="this.style.behavior=''url(#default#homepage)''; this.setHomePage(''你的网站名称);"><font color="000000" size="2" face="宋体">设为首页</font></a>
</body>
节日倒计时
<Script Language="JavaScript">
var timedate= new Date("October 1,2002");
var times="国庆节";
var now = new Date();
var date = timedate.getTime() - now.getTime();
var time = Math.floor(date / (1000 * 60 * 60 * 24));
if (time >= 0)
document.write("现在离"+times+"还有: "+time +"天")
</Script>
单击按钮打印出当前页
<Script Language="JavaScript">
if (window.print) {
document.write(''<form>''
+ ''<input type=button name=print value="打印本页" ''
+ ''onClick="javascript:window.print()"></form>'');
}
</Script>
单击按钮‘另存为’当前页
<input type="button" name="Button" value="保存本页" onClick="document.all.button.ExecWB(4,1)">
<object id="button" width=0 height=0 classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2">
<embed width="0" height="0"></embed>
</object>
显示系统当前日期
<script language=JavaScript>
today=new Date();
function date(){
this.length=date.arguments.length
for(var i=0;i<this.length;i++)
this[i+1]=date.arguments }
var d=new date("星期日","星期一","星期二","星期三","星期四","星期五","星期六");
document.write(
"<font color=##000000 style=''font-size:9pt;font-family: 宋体''> ",
today.getYear(),"年",today.getMonth()+1,"月",today.getDate(),"日",
d[today.getDay()+1],"</font>" );
</script>
不同时间段显示不同问候语 <Script Language="JavaScript">
var text=""; day = new Date( ); time = day.getHours( );
if (( time>=0) && (time < 7 ))
text="夜猫子,要注意身体哦! "
if (( time >= 7 ) && (time < 12))
text="今天的阳光真灿烂啊,你那个朋友呢?"
if (( time >= 12) && (time < 14))
text="午休时间。您要保持睡眠哦!"
if (( time >=14) && (time < 18))
text="祝您下午工作愉快! "
if ((time >= 18) && (time <= 22))
text="您又来了,可别和MM聊太久哦!"
if ((time >= 22) && (time < 24))
text="您应该休息了!"
document.write(text)
</Script>
水中倒影效果 <img id="reflect" src="你自己的图片文件名" width="175" height="59">
<script language="JavaScript">
function f1()
{
setInterval("mdiv.filters.wave.phase+=10",100);
}
if (document.all)
{
document.write(''<img id=mdiv src="''+document.all.reflect.src+''"
style="filter:wave(strength=3,freq=3,phase=0,lightstrength=30) blur() flipv()">'')
window.onload=f1
}
</script>
慢慢变大的窗口 <Script Language="JavaScript">
<!--
var Windowsheight=100
var Windowswidth=100
var numx=5
function openwindow(thelocation){
temploc=thelocation&, amp;, nbsp;
if
(!(window.resizeTo&&document.all)&&!(window.resizeTo&&document.getElementById))
{
window.open(thelocation)
return
}
windowsize=window.open("","","scrollbars")
windowsize.moveTo(0,0)
windowsize.resizeTo(100,100)
tenumxt()
}
function tenumxt(){
if (Windowsheight>=screen.availHeight-3)
numx=0
windowsize.resizeBy(5,numx)
Windowsheight+=5
Windowswidth+=5
if (Windowswidth>=screen.width-5)
{
windowsize.location=temploc
Windowsheight=100
Windowswidth=100
numx=5
return
}
setTimeout("tenumxt()",50)
}
//-->
</script>
<a href="javascript:openwindow(''http://www.31u.net'')">进入</a>
鼠标指向时弹出信息框
在<body></body>之间加上如下代码: <a href onmouseover="alert(''弹出信息!'')">显示的链接文字</a>
随机变换背景图象(一个可以刷新心情的特效)
在<head></head>之间加上如下代码:
<Script Language="JavaScript">
image = new Array(4); //定义image为图片数量的数组
image [0] = ''tu0.gif'' //背景图象的路径
image [1] = ''tu1.gif''
image [2] = ''tu2.gif''
image [3] = ''tu3.gif''
image [4] = ''tu4.gif''
number = Math.floor(Math.random() * image.length);
document.write("<BODY BACKGROUND="+image[number]+">");
</Script>
鼠标一碰就给颜色看的链接 在<body></body>之间加上如下代码:
<p onMouseMove="anniu()">你敢碰我,我就给点颜色你看!</p>
<Script Language = "VBScript">
sub anniu
document.fgColor=int(256*256*256*rnd)
end sub
</Script>
从天而降并有幻影效果的窗口
<head>
<Script language="JavaScript">
function move(x) {
if(self.moveBy){
self.moveBy (0,-800);
for(i = x; i > 0; i--)
{
self.moveBy(0,3);
}
for(j = 200; j > 0; j--){ //如果你认为窗口抖动厉害,就200换成个位数
self.moveBy(0,j);
self.moveBy(j,0);
self.moveBy(0,-j);
self.moveBy(-j,0);
}
}
}
</Scrip>
<body bgColor=#ffffff onload=move(280)>
</body>
</head>
表格的半透明显示效果 在<head></head>之间加上如下代码:
<style>
.alpha{filter: Alpha(Opacity=50)} //50表示50%的透明度
</style>
在<body></body>之间加上如下代码:
<table border="1" width="100" height="62" class="alpha" bgcolor="#F2A664" >
<tr>
<td width="100%" height="62">
<div align="center">很酷吧!</div>
</td>
</tr>
</table>
锁定状态栏文字防止显示地址
<body onmouseover="self.status=''文字'';return true">
禁止图片下载
在<body......>这里的最后加入:
oncontextmenu="return false" ondragstart="return false" onselectstart="return false" scroll="auto"
禁止缓存
<meta http-equiv="Expires" CONTENT="0">
<meta http-equiv="Cache-Control" CONTENT="no-cache">
<meta http-equiv="Pragma" CONTENT="no-cache">
加在HEAD里
使用包含页面
加密所包含页面地址,使用工具 htmlguardian5.3.5
目前功能最强的html代码加密软件,可以保护连接和html代码被盗。1.锁右键。2.禁鼠标圈选。3.不允许离线使用。4.密码保护。5.不显示状态栏url地址。6.全代码 或 局部代码保护。7.链接跟踪。8.禁止打印(IE5+)。9.压缩代码( 未加密前)。10.可加密*.html *.js *.asp *.vbs。11.两种不同加密算法。12.加密 frameset 结构。13.某些功能支持几个不同版本的浏览器。
下载flash我的三种方法:
--查看源文件,找出flash的绝对路径,复制,在flashget(或蚂蚁)中点任务
,然后点新建下载任务即可。
--在IE的临时文件夹Temporary Internet Files里把所有的东西都删掉,然后
刷新你想要下载flash的网页,即可得到你所要的flash
--使用外部软件,推荐使用Flash Catcher,安装后只需在你所要下载的flash上右键,save即可。
让IFRAME框架内的文档的背景透明
<iframe src="about:<body style=''background:transparent''>" allowtransparency></iframe>
进入页面后立即自动刷新?
<meta http-equiv="refresh" content="120;url=http://www.31u.net">
打开窗口即最大化
<script language="JavaScript">
<!-- Begin
self.moveTo(0,0)
self.resizeTo(screen.availWidth,screen.availHeight)
// End -->
</script>
能隐藏IFRAME的滚动条吗?我知道的三种方法:
1. 设置iframe scrolling="no"
2. 被包含页body应用overflow:hidden
3. 被包含页的body标签加scroll="no"
加入背景音乐
<bgsound src="mid/windblue[1].mid" loop="-1"> 只适用于IE
<embed src="music.mid" autostart="true" loop="true" hidden="true">
对Netscape ,IE 都适用
嵌入网页
<iframe name="tt" src="01a.html" width="450" height="287" scrolling="Auto" frameborder="0"></iframe>
跳转
<meta http-equiv="refresh" content="3;URL=list.htm">
滚动
<MARQUEE direction=up height=146 onmouseout=start() onmouseover=stop() scrollAmount=4>
</marquee>
细线分隔线
<hr noshade size=0 color=#C0C0C0>
过度方式
<meta http-equiv="Page-Exit" content="revealTrans(Duration=3,Transition=5)">
Duration的值为网页动态过渡的时间,单位为秒。
Transition是过渡方式,它的值为0到23,分别对应24种过渡方式。如下表:
0 盒状收缩 1 盒状放射
2 圆形收缩 3 圆形放射
4 由下往上 5 由上往下
6 从左至右 7 从右至左
8 垂直百叶窗 9 水平百叶窗
10 水平格状百叶窗 11垂直格状百叶窗
12 随意溶解 13从左右两端向中间展开
14从中间向左右两端展开 15从上下两端向中间展开
16从中间向上下两端展开 17 从右上角向左下角展开
18 从右下角向左上角展开 19 从左上角向右下角展开
20 从左下角向右上角展开 21 水平线状展开
22 垂直线状展开 23 随机产生一种过渡方式
如何控制横向和纵向滚动条的显隐?
<body style="overflow-y:hidden"> 去掉x轴
<body style="overflow-x:hidden"> 去掉y轴
<body scroll="no">不显
定义本网页关键字,可以在<Head></Head>中加入如下代码: <meta name="Keywords" content="china,enterprise,business,net">
Content 中所包含的就是关键字,你可以自行设置。
这里有个技巧,你可以重复某一个单词,这样可以提高自己网站的排行位置,如:
<meta name="Keywords" content="china,china,china,china">
IE5.0 的部分快捷键:
A:打开查找功能:Ctrl+F
关闭浏览器窗口:Ctrl+W
打开地址栏下拉列表框:F4
刷 新:F5
将当前Web页保存到收藏夹列表:Ctrl+D
打开当前 IE 窗口的一个拷贝:Ctrl+N
停止下载当前网页:Esc
光标迅速移动到网页的开头:Home
光标迅速移动到网页的尾部:End
打开新的地址键入窗口:Ctrl+O
打开收藏夹:Ctrl+I
打开历史记录文件夹:Ctrl+H
打开浏览器设定的默认主页:Alt+HOME
添加到收藏夹:
<a href="javascript:window.external.addFavorite(''http://链接'',''说明'');">添加到收藏夹</a>
设为首页:
<a href=# onclick=this.style.behavior=''url(#default#homepage)'';this.setHomePage (''http://链接'');>设为首页</a>
定制浏览器地址栏前的小图标:
A:在网页的<head></head>间加入以下语句
<link rel="shortcuticon" href="http://…/icon.ico">
即可。其中 icon.ico 为 16x16 的图标文件,
颜色不要超过 16 色。
把滚动条放在浏览器窗口的左边
A:在 <body> 中加 dir=RTL,即 <body dir=RTL>。
让背景图不滚动
IE浏览器支持一个 Body 属性 bgproperties,它可以让背景不滚动:
<Body Background="图片文件" bgproperties="fixed">
删除确认:
<input type="button" name="DEL" onclick="{if(confirm(''确认删除么?'')){location.href=''xxx.asp'';}return false;}" value="ON" >
隐藏状态栏中的链接地址:
<script language="javascript">
kstatus();
function kstatus(){
self.status="GBlog () ";
setTimeout("kstatus()",0);
}
</script>
自定义指定区域的文字大小:
<div id=zoom>sdrrrrrrrrrrrrrrrrrrrrrrrrrrrrr</div>
【<A href="javascript:doZoom(16)">大</A> <A href="javascript:doZoom(14)">中</A> <A href="javascript:doZoom(12)">小</A>】
<SCRIPT language=JavaScript>
function doZoom(size){
document.getElementById(''zoom'').style.fontSize=size+''px''
}
</script>
Input输入框文字效果:
<input type="text" value="123456" style="FONT-size:38px;color:red;font-family:arial black">
通过层来实现渐淡淡出
<script language="JavaScript1.2">
function makevisible(cur,which){
if (which==0)
cur.filters.alpha.opacity=100
else
cur.filters.alpha.opacity=50
}
</script>
<div style="width:200px;height:200px;filter:alpha(opacity=50);border:1px solid #000;background:#efefef" onMouseOver="makevisible(this,0)" onMouseOut="makevisible(this,1)">
ywicc.com
</div>
网页屏保
<script language="JavaScript">
function screensave(){
test.value++;
if(test.value==5){
test.style.display=''none'';
document.all[4].bgColor=''black'';
}
}
function screenopen(){
test.value=0;
test.style.display='''';
document.all[4].bgColor='''';
}
</script>
<body onkeydown="screenopen()" onmousemove="screenopen()" onload="setInterval(''screensave()'',1000)">
5 秒屏保<input id="test">
让标题动态
<script>
<!--
var tx = new Array (
"◇:::::::网页制作学习园地:::::::◇欢迎您!◇",
"◆欢迎大家光临网页制作学习园地网站!◆",
"◆大量供应网页制作教材,资料,源代码,网页制作软件,相关插件光盘!◆",
"◆最可怕的敌人,就是没有坚强的信念!◆",
"◆应该让别人的生活因为有了你的生存而更加美好!◆"
);
var txcount=5;
var i=1;
var wo=0;
var ud=1;
function animatetitle()
{
window.document.title=tx[wo].substr(0, i)+"_";
if (ud==0) i--;
if (ud==1) i++;
if (i==-1) {ud=1;i=0;wo++;wo=wo%txcount;}
if (i==tx[wo].length+10) {ud=0;i=tx[wo].length;}
// if (window.document.title.length < 20 ) window.document.title=window.document.title+"-";
// if (window.document.title.length == 20 ) window.document.title=window.document.title+"]";
// if (window.document.title.length == 21 ) setTimeout("window.document.title=''Animierte Seitentitel ''; ",1000);
parent.window.document.title=tx[wo].substr(0, i)+"_";
setTimeout("animatetitle()",100);
}
animatetitle();
// --></script><script language="JavaScript">
<!--
function MM_openBrWindow(theURL,winName,features) { //v2.0
window.open(theURL,winName,features);
}
//-->
</script>
隐去浏览器中当鼠标移到图片上跳出的工具栏
<img galleryimg="no">
或者
<head>
<meta http-equiv="imagetoolbar" content="no">
</head>
在form中只有input输入框的情况下...在这个input输入框中按enter进行提交表单
<form onsubmit="if(event.srcElement.name==''bb''){this.submit()}else{return false}">
<input name=a size=20>
<input type=button name=bb onclick="submit();">
</form>
删除确认
<input type="button" value="删除" onclick="{if(confirm(''确认删除么?'')){location.href=''aa.asp'';}return false;}">
或
<a href="http://www.31u.net/search.asp" onclick="{if(confirm(''确定删除吗?'')){return true;}return false;}">删除</a>
或
<a href="http://www.31u.net/search.asp" onclick="return confirm(''该删除操作将无法恢复!是否继续?'')">删除</a>
返回页面顶部:
javascript:window.scroll(0,0)
离开页面时弹出警告:
<BODY onbeforeunload="checkclose()">
<SCRIPT>
function checkclose(){
event.returnValue = "测试啊" //XXX可以改为任何文本信息也可以是空
}
</SCRIPT>
<a href="http://www.31u.net/search.asp">aa</a>
7:07 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | 计算机与 Internet
固定链接 关闭
http://spaces.msn.com/members/lionyang888/Blog/cns!1pegtqF_uRpLTqjlUYAIJKVQ!179.entry
WEB编程开发常用的代码
WEB编程开发常用的代码
2005-9-29 15:17:20 编辑:阿志 来源:来源网络
1. ASP与Access数据库连接:
dim conn,mdbfile
mdbfile=server.mappath("数据库名称.mdb")
set conn=server.createobject("adodb.connection")
''conn.open "driver={microsoft access driver (*.mdb)};uid=admin;pwd=数据库密码;dbq="&mdbfile
conn.open "Provider = Microsoft.Jet.OLEDB.4.0;Data Source = " & mdbfile
2. ASP与SQL数据库连接: dim conn
set conn=server.createobject("ADODB.connection")
con.open "PROVIDER=SQLOLEDB;DATA SOURCE=SQL服务器名称或IP地址;UID=sa;PWD=数据库密码;DATABASE=数据库名称;"
建立记录集对象: set rs=server.createobject("adodb.recordset")
rs.open SQL语句,conn,3,2
SQL常用命令使用方法:
数据记录筛选: sql="select * from 数据表 where 字段名=字段值 order by 字段名 "
sql="select * from 数据表 where 字段名 like ‘%字段值%‘ order by 字段名 "
sql="select top 10 * from 数据表 where 字段名 order by 字段名 "
sql="select * from 数据表 where 字段名 in (‘值1‘,‘值2‘,‘值3‘)"
sql="select * from 数据表 where 字段名 between 值1 and 值2"
更新数据记录: sql="update 数据表 set 字段名=字段值 where 条件表达式"
sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式"
删除数据记录: sql="delete from 数据表 where 条件表达式"
sql="delete from 数据表" (将数据表所有记录删除)
添加数据记录: sql="insert into 数据表 (字段1,字段2,字段3 …) valuess (值1,值2,值3 …)"
sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)
数据记录统计函数:
AVG(字段名) 得出一个表格栏平均值
COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(字段名) 取得一个表格栏最大的值
MIN(字段名) 取得一个表格栏最小的值
SUM(字段名) 把数据栏的值相加
引用以上函数的方法: sql="select sum(字段名) as 别名 from 数据表 where 条件表达式"
set rs=conn.excute(sql)
用 rs("别名") 获取统的计值,其它函数运用同上。
数据表的建立和删除: Create TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )
例:Create TABLE tab01(name varchar(50),datetime default now())
Drop TABLE 数据表名称 (永久性删除一个数据表)
记录集对象的方法:
rs.movenext 将记录指针从当前的位置向下移一行
rs.moveprevious 将记录指针从当前的位置向上移一行
rs.movefirst 将记录指针移到数据表第一行
rs.movelast 将记录指针移到数据表最后一行
rs.absoluteposition=N 将记录指针移到数据表第N行
rs.absolutepage=N 将记录指针移到第N页的第一行
rs.pagesize=N 设置每页为N条记录
rs.pagecount 根据 pagesize 的设置返回总页数
rs.recordcount 返回记录总数
rs.bof 返回记录指针是否超出数据表首端,true表示是,false为否
rs.eof 返回记录指针是否超出数据表末端,true表示是,false为否
rs.delete 删除当前记录,但记录指针不会向下移动
rs.addnew 添加记录到数据表末端
rs.update 更新数据表记录
判断所填数据是数字型
if not isNumeric(request("字段名称")) then
response.write "不是数字"
else
response.write "数字"
end if
页面执行时间:
<%startime = Timer()%>
.... ....
内容
... ...
结尾
<%
Dim Endtime
Endtime = Timer()
response.write "页面执行时间:<font color=red>"&FormatNumber((Endtime-Startime)*1000,5)&"</font> 毫秒"
%>
定义打开网页时起始窗口的大小
<script for="window" event="onload">
window.resizeTo(500,300)
</script>
随机数:
<%randomize%>
<%=(int(rnd()*n)+1)%>
查询数据时得到的记录关键字用红色显示:
replace(RS("字段X"),searchname,"<font color=#FF0000>" & searchname & "</font>")
通过asp的手段来检查来访者是否用了代理
<% if Request.ServerVariables("HTTP_X_FORWARDED_FOR")<>"" then
response.write "<font color=#FF0000>您通过了代理服务器,"& _
"真实的IP为"&Request.ServerVariables("HTTP_X_FORWARDED_FOR")
end if
%>
判断上一页的来源
request.servervariables("HTTP_REFERER")
javascript: document.referrer
清除缓存,重新加载页面
<%response.expires = 0
response.expiresabsolute = now() - 1
response.addHeader "pragma","no-cache"
response.addHeader "cache-control","private"
Response.cachecontrol = "no-cache"
%>
检索并删除数据库里的重复记录
conn.execute("delete from table where id not in (select distinct from table)")
文件删除函数 <%
''文件删除函数
function deletefile(filename)
if filename<>"" then
set fso=server.CreateObject("scripting.filesystemobject")
if fso.FileExists(filename) then
fso.DeleteFile filename
else
Response.Write "<script>alert(’该文件不存在’);</script>"
end if
end if
end function
strfile=server.MapPath("fileName")
deletefile(strfile)
%>
ASP字数计算函数 <%
Function WordCount(strInput)
Dim strTemp
strTemp = Replace(strInput, vbTab, " ")
strTemp = Replace(strTemp, vbCr, " ")
strTemp = Replace(strTemp, vbLf, " ")
'' 删除字首字尾空格
strTemp = Trim(strTemp)
'' 替换为一个空格
Do While InStr(1, strTemp, " ", 1) <> 0
strTemp = Replace(strTemp, " ", " ")
Loop
WordCount = UBound(Split(strTemp, " ", -1, 1)) +1
End Function
%>
全正则的检测IP是否合法的函数 function checkIP2(sIPAddress)
{
var exp=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
var reg = sIPAddress.match(exp);
var ErrMsg="你输入的是一个非法的IP地址段!\nIP段为::xxx.xxx.xxx.xxx(xxx为0-255)!"
var Msg="你输入的是一个合法的IP地址段!"
if(reg==null)
{
alert(ErrMsg);
}
else
{
alert(reg);
}
}
关闭子窗口时刷新父窗口 在子窗口
<script language="javascript">
window.opener.location="父窗口页面"
window.close()
</script>
文本框输入限制:
<script>
function regInput(obj, reg, inputStr)
{
var docSel = document.selection.createRange()
if (docSel.parentElement().tagName != "INPUT") return false
oSel = docSel.duplicate()
oSel.text = ""
var srcRange = obj.createTextRange()
oSel.setEndPoint("StartToStart", srcRange)
var str = oSel.text + inputStr + srcRange.text.substr(oSel.text.length)
return reg.test(str)
}
</script>
小写英文:<xmp style= "display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[a-z]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[a-z]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[a-z]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
><br>
大写英文:<xmp style= "display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[A-Z]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[A-Z]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[A-Z]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled">
<br>
任意数字:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[0-9]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[0-9]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[0-9]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
><br>
限2位小数:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^\d*\.?\d{0,2}$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^\d*\.?\d{0,2}$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^\d*\.?\d{0,2}$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
> 如: 123.12<br>
日 期:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^\d{1,4}([-\/](\d{1,2}([-\/](\d{1,2})?)?)?)?$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^\d{1,4}([-\/](\d{1,2}([-\/](\d{1,2})?)?)?)?$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^\d{1,4}([-\/](\d{1,2}([-\/](\d{1,2})?)?)?)?$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
> 如: 2002-9-29<br>
任意中文:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[\u4E00-\u9FA5]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[\u4E00-\u9FA5]*$/, event.dataTransfer.getData(''Text''))"
><br>
部分英文:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[a-e]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[a-e]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[a-e]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
> 范围: a,b,c,d,e<br>
部分中文:<xmp style="display:inline"> </xmp>
<script language=javascript>
function checkChinese(oldLength, obj)
{
var oTR = window.document.selection.createRange()
var reg = /[^一二三四五六七八九十]/g
oTR.moveStart("character", -1*(obj.value.length-oldLength))
oTR.text = oTR.text.replace(reg, "")
}
</script>
<input onkeypress="return false" onkeydown="setTimeout(''checkChinese(''+this.value.length+'',''+this.uniqueID+'')'', 1)"
onpaste = "return regInput(this, /^[一二三四五六七八九十]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[一二三四五六七八九十]*$/, event.dataTransfer.getData(''Text''))"
> 范围: 一二三四五六七八九十<br>
[Ctrl+A 全选 Ctrl+C 复制]
不能点右键,不用CTRL+A,不能复制作!
<body oncontextmenu="window.event.returnValue=false"
onkeypress="window.event.returnValue=false"
onkeydown="window.event.returnValue=false"
onkeyup="window.event.returnValue=false"
ondragstart="window.event.returnValue=false"
onselectstart="event.returnValue=false">
</body>
显示状态拦固定文字:
放在body前
<base onmouseover="window.status=''这里是Goaler的Blog系统,欢迎访问'';return true">
用键盘打开网页 <script language=javascript>
document.onkeydown=gopage
var add="Admin/AddArticle.asp"
var logon="Admin/Logon.asp"
function gopage() {
if (event.keyCode==13) location=add
if (event.keyCode==38) location=logon
}
</script>
根据内容自动调整iframe高度 有时为了方便使用Iframe,但被潜入的页面长度不是固定的,显示滚动条不仅影响美观还对用户操作带来不便,自动调整高度可以解决这个问题。^_^
function f_frameStyleResize(targObj)
{
var targWin = targObj.parent.document.all[targObj.name];
if(targWin != null)
{
var HeightValue = targObj.document.body.scrollHeight
if(HeightValue < 600){HeightValue = 600} //不小于600
targWin.style.pixelHeight = HeightValue;
}
}
function f_iframeResize()
{
bLoadComplete = true;
f_frameStyleResize(self);
}
var bLoadComplete = false;
window.onload = f_iframeResize;
禁止页面正文内容被选取
<body oncontextmenu="return false" ondragstart="return false" onselectstart ="return false" onselect="document.selection.empty()" oncopy="document.selection.empty()" onbeforecopy="return
false"onmouseup="document.selection.empty()">
消除ie6自动出现的图像工具栏,设置 GALLERYIMG属性为false或no .
<IMG SRC="mypicture.jpg" HEIGHT="100px" WIDTH="100px" GALLERYIMG="no">
防止点击空链接时,页面往往重置到页首端。
代码“javascript:void(null)”代替原来的“#”标记
如何避免别人把你的网页放在框架中
<script language=“javascript”><!--if (self!=top){top.location=self.location;} -->< /script>
页面定时刷新
<meta http-equiv="Refresh" content="秒" >
页面定时转向新的地址
<meta http-equiv="refresh" content="秒;URL=url">
关闭窗口,这个是不会弹出提示直接关的:
把如下代码加入<body>区域中
<OBJECT id=closes type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
<param name="Command" value="Close">
</object>
<script language="JavaScript">function shutwin(){closes.Click();return;}</script>
<a href="javascript:shutwin();">关闭本窗口</a>
有时候好不容易写出来的程序代码被别人抄去,心里一定不好受。这还是小事,但如果在我们的源代码中有一些不希望让别人知道的内容,比如密码、Action的指向等,这些一旦被人利用,那后果有时是不堪设想的。而网页加密就是我们现在需要解决的问题。下面就我在网页制作中的一些经验向大家介绍一些简单的防范方法。
禁止右键
看到这里大家一定会想,这招有很多人介绍过了,而且破解的方法也有很多。但我这里要说的是另一种方法,而且我试了很多方法都没有能破解。具体如下:
<html>
<head>
<script>
function stop(){
alert("试试能破解吗?");
return false;
}
document.oncontextmenu=stop;
</script>
<boyd>你可以按右键、shift+F10和右ctrl左边的那个键试试!看能不能解。^_^</body>
大家试试,看能不能破解!你可以将alert("试试能破解吗?");这句去掉,这样当按右键时就什么反应也没有了,就好像没有右键功能一样。
禁示查看源代码
我们已经禁了右键,但从"查看"菜单下的"源文件"中同样可以看到源代码,下面我们就来解决这个问题:
其实这只要使用一个含有<frame></frame>标记的网页便可以达到目的。
<frameset>
<frame src="你要保密的文件的URL">
</frameset>
这样当有人使用"查看"下的"源文件"的时候,看到的将是上面的那段代码,而你真正的文件又躲过一劫。
禁示另存为
通过上面的两步好像你的源代码已经安全了,但别忘了,别人还可以将你的页面保存下来,再慢慢分析。不过别担心,下面我们来解决这个问题。
在你要保密的网页中加入以下代码:
<noscript><iframe src="*.htm"></iframe></noscript>
彻底屏蔽右键方法。
<body oncontextmenu="return false">
双击页面后自动滚屏,单击后停止。
<SCRIPT language=JavaScript>
var currentpos,timer;
function initialize()
{ timer=setInterval("scrollwindow()",16); }
function sc(){
clearInterval(timer);
}
function scrollwindow()
{currentpos=document.body.scrollTop;
window.scroll(0,++currentpos);
if (currentpos != document.body.scrollTop)
sc();
}
document.onmousedown=sc
document.ondblclick=initialize
</script>
设定脚本出错能继续运行
<script language="javascript">
function KillError()
{
return false;
}
window.onerror=KillError;
</script>
7:00 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | 计算机与 Internet
固定链接 关闭
http://spaces.msn.com/members/lionyang888/Blog/cns!1pegtqF_uRpLTqjlUYAIJKVQ!178.entry
一些不常用的html代码
1. oncontextmenu="window.event.returnvalue=false" 将彻底屏蔽鼠标右键
<table border oncontextmenu=return(false)><td>no</table> 可用于Table
2. <body onselectstart="return false"> 取消选取、防止复制
3. onpaste="return false" 不准粘贴
4. oncopy="return false;" oncut="return false;" 防止复制
5. <link rel="Shortcut Icon" href="favicon.ico"> IE地址栏前换成自己的图标
6. <link rel="Bookmark" href="favicon.ico"> 可以在收藏夹中显示出你的图标
7. <input style="ime-mode:disabled"> 关闭输入法
8. 永远都会带着框架
<script language="javascript"><!--
if (window == top)top.location.href = "frames.htm"; //frames.htm为框架网页
// --></script>
9. 防止被人frame
<SCRIPT LANGUAGE=javascript><!--
if (top.location != self.location)top.location=self.location;
// --></SCRIPT>
10. <noscript><iframe src=*.html></iframe></noscript> 网页将不能被另存为
11. <input type=button value=查看网页源代码
onclick="window.location = ''view-source:''+ ''http://www.csdn.net/'">
12. 怎样通过asp的手段来检查来访者是否用了代理
<% if Request.ServerVariables("HTTP_X_FORWARDED_FOR")<>"" then
response.write "<font color=#FF0000>您通过了代理服务器,"& _
"真实的IP为"&Request.ServerVariables("HTTP_X_FORWARDED_FOR")
end if
%>
13. 取得控件的绝对位置
//javascript
<script language="javascript">
function getIE(e){
var t=e.offsetTop;
var l=e.offsetLeft;
while(e=e.offsetParent){
t+=e.offsetTop;
l+=e.offsetLeft;
}
alert("top="+t+"\nleft="+l);
}
</script>
//VBScript
<script language="VBScript"><!--
function getIE()
dim t,l,a,b
set a=document.all.img1
t=document.all.img1.offsetTop
l=document.all.img1.offsetLeft
while a.tagName<>"BODY"
set a = a.offsetParent
t=t+a.offsetTop
l=l+a.offsetLeft
wend
msgbox "top="&t&chr(13)&"left="&l,64,"得到控件的位置"
end function
--></script>
14. 光标是停在文本框文字的最后
<script language="javascript">
function cc()
{
var e = event.srcElement;
var r =e.createTextRange();
r.moveStart(''character'',e.value.length);
r.collapse(true);
r.select();
}
</script>
<input type=text name=text1 value="123" onfocus="cc()">
15. 判断上一页的来源
asp:
request.servervariables("HTTP_REFERER")
javascript:
document.referrer
16. 最小化、最大化、关闭窗口
<object id=hh1 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11">
<param name="Command" value="Minimize"></object>
<object id=hh2 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11">
<param name="Command" value="Maximize"></object>
<OBJECT id=hh3 classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
<PARAM NAME="Command" value="Close"></OBJECT>
<input type=button value=最小化 onclick=hh1.Click()>
<input type=button value=最大化 onclick=hh2.Click()>
<input type=button value=关闭 onclick=hh3.Click()>
本例适用于IE
17.
<%
''定义数据库连接的一些常量
Const adOpenForwardOnly = 0 ''游标只向前浏览记录,不支持分页、Recordset、BookMark
Const adOpenKeyset = 1 ''键集游标,其他用户对记录说做的修改将反映到记录集中,但其他用户增加或删除记录不会反映到记录集中。支持分页、Recordset、BookMark
Const adOpenDynamic = 2 ''动态游标功能最强,但耗资源也最多。用户对记录说做的修改,增加或删除记录都将反映到记录集中。支持全功能浏览(ACCESS不支持)。
Const adOpenStatic = 3 ''静态游标,只是数据的一个快照,用户对记录说做的修改,增加或删除记录都不会反映到记录集中。支持向前或向后移动
Const adLockReadOnly = 1 ''锁定类型,默认的,只读,不能作任何修改
Const adLockPessimistic = 2 ''当编辑时立即锁定记录,最安全的方式
Const adLockOptimistic = 3 ''只有在调用Update方法时才锁定记录集,而在此前的其他操作仍可对当前记录进行更改、插入和删除等
Const adLockBatchOptimistic = 4 ''当编辑时记录不会被锁定,而更改、插入和删除是在批处理方式下完成的
Const adCmdText = &H0001
Const adCmdTable = &H0002
%>
18. 网页不会被缓存
HTM网页
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
或者<META HTTP-EQUIV="expires" CONTENT="0">
ASP网页
Response.Expires = -1
Response.ExpiresAbsolute = Now() - 1
Response.cachecontrol = "no-cache"
PHP网页
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
19. 检查一段字符串是否全由数字组成
<script language="javascript"><!--
function checkNum(str){return str.match(/\D/)==null}
alert(checkNum("1232142141"))
alert(checkNum("123214214a1"))
// --></script>
20. 获得一个窗口的大小
document.body.clientWidth,document.body.clientHeight
21. 怎么判断是否是字符
if (/[^\x00-\xff]/g.test(s)) alert("含有汉字");
else alert("全是字符");
22.TEXTAREA自适应文字行数的多少
<textarea rows=1 name=s1 cols=27 onpropertychange="this.style.posHeight=this.scrollHeight">
</textarea>
23. 日期减去天数等于第二个日期
<script language=javascript>
function cc(dd,dadd)
{
//可以加上错误处理
var a = new Date(dd)
a = a.valueOf()
a = a - dadd * 24 * 60 * 60 * 1000
a = new Date(a)
alert(a.getFullYear() + "年" + (a.getMonth() + 1) + "月" + a.getDate() + "日")
}
cc("12/23/2002",2)
</script>
24. 选择了哪一个Radio
<HTML><script language="vbscript">
function checkme()
for each ob in radio1
if ob.checked then window.alert ob.value
next
end function
</script><BODY>
<INPUT name="radio1" type="radio" value="style" checked>Style
<INPUT name="radio1" type="radio" value="barcode">Barcode
<INPUT type="button" value="check" onclick="checkme()">
</BODY></HTML>
25.获得本页url的request.servervariables("")集合
Response.Write "<TABLE border=1><!-- Table Header --><TR><TD><B>Variables</B></TD><TD><B>value</B></TD></TR>"
for each ob in Request.ServerVariables
Response.Write "<TR><TD>"&ob&"</TD><TD>"&Request.ServerVariables(ob)&"</TD></TR>"
next
Response.Write "</TABLE>"
26.
本机ip<%=request.servervariables("remote_addr")%>
服务器名<%=Request.ServerVariables("SERVER_NAME")%>
服务器IP<%=Request.ServerVariables("LOCAL_ADDR")%>
服务器端口<%=Request.ServerVariables("SERVER_PORT")%>
服务器时间<%=now%>
IIS版本<%=Request.ServerVariables"SERVER_SOFTWARE")%>
脚本超时时间<%=Server.ScriptTimeout%>
本文件路径<%=server.mappath(Request.ServerVariables("SCRIPT_NAME"))%>
服务器CPU数量<%=Request.ServerVariables("NUMBER_OF_PROCESSORS")%>
服务器解译引擎<%=ScriptEngine & "/"& ScriptEngineMajorVersion &"."&ScriptEngineMinorVersion&"."& ScriptEngineBuildVersion %>
服务器操作系统<%=Request.ServerVariables("OS")%>
27.ENTER键可以让光标移到下一个输入框
<input onkeydown="if(event.keyCode==13)event.keyCode=9">
28. 检测某个网站的链接速度:
把如下代码加入<body>区域中:
<script language=javascript>
tim=1
setInterval("tim++",100)
b=1
var autourl=new Array()
autourl[1]="www.njcatv.net"
autourl[2]="javacool.3322.net"
autourl[3]="www.sina.com.cn"
autourl[4]="www.nuaa.edu.cn"
autourl[5]="www.cctv.com"
function butt(){
document.write("<form name=autof>")
for(var i=1;i<autourl.length;i++)
document.write("<input type=text name=txt"+i+" size=10 value=测试中……> =》<input type=text name=url"+i+" size=40> =》<input type=button value=GO onclick=window.open(this.form.url"+i+".value)><br/>")
document.write("<input type=submit value=刷新></form>")
}
butt()
function auto(url){
document.forms[0]["url"+b].value=url
if(tim>200)
{document.forms[0]["txt"+b].value="链接超时"}
else
{document.forms[0]["txt"+b].value="时间"+tim/10+"秒"}
b++
}
function run(){for(var i=1;i<autourl.length;i++)document.write("<img src=http://"+autourl[i]+"/"+Math.random()+" width=1 height=1 onerror=auto(''http://";;;+autourl[i]+"'')>")}
run()</script>
29. 各种样式的光标
auto :标准光标
default :标准箭头
hand :手形光标
wait :等待光标
text :I形光标
vertical-text :水平I形光标
no-drop :不可拖动光标
not-allowed :无效光标
help :?帮助光标
all-scroll :三角方向标
move :移动标
crosshair :十字标
e-resize
n-resize
nw-resize
w-resize
s-resize
se-resize
sw-resize
1、 去掉IE的滚动条
有时候做好的网页明明没有超出窗口,可IE却偏偏给加上滚动条,这样看上去很不舒服,其实这也是可以通过一些小技巧避免的。具体如下:
<body style=”overflow-x:hidden”>…</body> //去掉X轴方向的滚动条
<body style=”overflow-y:hidden”>…</body> //去掉Y轴方向的滚动条
<body style=”overflow:hidden”>…</body> //去掉全部的滚动条
现在你看到的和你想像中的网页应该一样了吧,如果其中有什么不明白的地方可以参照注释中的说明。
2、 使网页中的复制无效
有方法防止网页被保存了(参见《你别看我的源代码》),可不可以也防止网页内容被复制呢?答案是当然可以。看看下面的例子你就会明白的。
<html>
<head>
<script language=”javascript”>
function nocopy() {
alert(“对不起,你不能非法复制本站内容”);
event.returnvalue=false;
}
</script>
</head>
<body oncopy=”nocopy()”>copyright by commander.</body>
</html>
这其实中是利用了document的一个oncopy事件,也就是说当发生复制事件时,弹出警告框,同时事件(event)的返回值为false使oncopy事件失效,从而达到防止复制的目的。
3、 用脚本控制浏览器
看到标题是不是有点不相信,那么试试下面的这几个例子吧!你一定会吃惊的。
在<body>和</body>之间加入如下代码:
<button onclick=”document.execCommand(‘open’)”>打开</button>
<button onclick=”document.execCommand(‘saveas’)”>另存为…</button>
<button onclick=”document.execCommand(‘print’)”>打印</button>
上面其实都是利用了document.execCommand()这个内置的函数,其参数为相应的浏览器命令,还有很多命令就留给大家自己发现吧!
4、 IFrame也可以编辑文字
有没有想过除了表单(<form>)之外还有其它的网页元素可以编辑文字呢?只要使用IFrame的隐藏的一个属性就可以使IFrame成为一个文本编辑器。
<html>
<body onload=”editer.document.designMode=’On’”>
<IFrame ID=”editer”></IFrame>
</body>
</html>
其中designMode属性表示IFrame的设计模式的状态(开/关),还在犹豫什么呢,快试试吧!
只要巧妙的利用这一特性就可以制作很多意想不到的效果。如果下面我们来做一个图片编辑器。
<html>
<body onload=”imgEditer.document.designMode=’On’;imgEditer.document.write(‘<img src=图片.gif>’)”>
<IFrame id=”imgEditer”></IFrame>
</body>
</html>
用鼠标点击图片是不是有新的发现,其实大家只要利用自己的想象和充分利用这个属性一定能做出更多的花样来,别忘了到时候有什么新的东东,告诉我一声呀!(Email:[email protected])
5、 打开硬盘
这是打开硬盘的另一种方法,把它写出来只是想告诉大家,要达到同一个目的有很多种方法,这里就是利用了表单的Action属性达到的,其实打开硬盘有很多种方法,只是这种不太被人们注意,所以这里就选择了这种方法。
<form action=file ://c|><input type=”submit” value=”打开C盘”></form>
<script language=JavaScript>
document.write("最后更新时间: " + document.lastModified + "")
</script>
2秒后关闭当前页
<script language="JavaScript">
<!--
setTimeout(''window.close();'',2000);
-->
</script>
2秒后载入指定网页
<head>
<meta http-equiv="refresh" content="2;URL=http://你的网址">
</head>
添加到收藏夹
<Script Language="JavaScript">
function bookmarkit()
{
window.external.addFavorite(''http://你的网址'',''你的网站名称'')
}
if (document.all)document.write(''<a href="#" onClick="bookmarkit()">加入收藏夹</a>'')
</Script>
禁止鼠标右键的动作
<Script Language = "JavaScript">
function click() { if (event.button==2||event.button==3)
{
alert(''禁止鼠标右键'');
}
document.onmousedown=click // -->
</Script>
或
<script language="JavaScript">
function click() { if (event.button==2)
{alert(''*^_^*''); } } document.onmousedown=click // -->
</script>
设置该页为首页
<body bgcolor="#FFFFFF" text="#000000">
<a class="chlnk" style="cursor:hand" HREF onClick="this.style.behavior=''url(#default#homepage)''; this.setHomePage(''你的网站名称);"><font color="000000" size="2" face="宋体">设为首页</font></a>
</body>
节日倒计时
<Script Language="JavaScript">
var timedate= new Date("October 1,2002");
var times="国庆节";
var now = new Date();
var date = timedate.getTime() - now.getTime();
var time = Math.floor(date / (1000 * 60 * 60 * 24));
if (time >= 0)
document.write("现在离"+times+"还有: "+time +"天")
</Script>
单击按钮打印出当前页
<Script Language="JavaScript">
if (window.print) {
document.write(''<form>''
+ ''<input type=button name=print value="打印本页" ''
+ ''onClick="javascript:window.print()"></form>'');
}
</Script>
单击按钮‘另存为’当前页
<input type="button" name="Button" value="保存本页" onClick="document.all.button.ExecWB(4,1)">
<object id="button" width=0 height=0 classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2">
<embed width="0" height="0"></embed>
</object>
显示系统当前日期
<script language=JavaScript>
today=new Date();
function date(){
this.length=date.arguments.length
for(var i=0;i<this.length;i++)
this[i+1]=date.arguments }
var d=new date("星期日","星期一","星期二","星期三","星期四","星期五","星期六");
document.write(
"<font color=##000000 style=''font-size:9pt;font-family: 宋体''> ",
today.getYear(),"年",today.getMonth()+1,"月",today.getDate(),"日",
d[today.getDay()+1],"</font>" );
</script>
不同时间段显示不同问候语 <Script Language="JavaScript">
var text=""; day = new Date( ); time = day.getHours( );
if (( time>=0) && (time < 7 ))
text="夜猫子,要注意身体哦! "
if (( time >= 7 ) && (time < 12))
text="今天的阳光真灿烂啊,你那个朋友呢?"
if (( time >= 12) && (time < 14))
text="午休时间。您要保持睡眠哦!"
if (( time >=14) && (time < 18))
text="祝您下午工作愉快! "
if ((time >= 18) && (time <= 22))
text="您又来了,可别和MM聊太久哦!"
if ((time >= 22) && (time < 24))
text="您应该休息了!"
document.write(text)
</Script>
水中倒影效果 <img id="reflect" src="你自己的图片文件名" width="175" height="59">
<script language="JavaScript">
function f1()
{
setInterval("mdiv.filters.wave.phase+=10",100);
}
if (document.all)
{
document.write(''<img id=mdiv src="''+document.all.reflect.src+''"
style="filter:wave(strength=3,freq=3,phase=0,lightstrength=30) blur() flipv()">'')
window.onload=f1
}
</script>
慢慢变大的窗口 <Script Language="JavaScript">
<!--
var Windowsheight=100
var Windowswidth=100
var numx=5
function openwindow(thelocation){
temploc=thelocation&, amp;, nbsp;
if
(!(window.resizeTo&&document.all)&&!(window.resizeTo&&document.getElementById))
{
window.open(thelocation)
return
}
windowsize=window.open("","","scrollbars")
windowsize.moveTo(0,0)
windowsize.resizeTo(100,100)
tenumxt()
}
function tenumxt(){
if (Windowsheight>=screen.availHeight-3)
numx=0
windowsize.resizeBy(5,numx)
Windowsheight+=5
Windowswidth+=5
if (Windowswidth>=screen.width-5)
{
windowsize.location=temploc
Windowsheight=100
Windowswidth=100
numx=5
return
}
setTimeout("tenumxt()",50)
}
//-->
</script>
<a href="javascript:openwindow(''http://www.31u.net'')">进入</a>
鼠标指向时弹出信息框
在<body></body>之间加上如下代码: <a href onmouseover="alert(''弹出信息!'')">显示的链接文字</a>
随机变换背景图象(一个可以刷新心情的特效)
在<head></head>之间加上如下代码:
<Script Language="JavaScript">
image = new Array(4); //定义image为图片数量的数组
image [0] = ''tu0.gif'' //背景图象的路径
image [1] = ''tu1.gif''
image [2] = ''tu2.gif''
image [3] = ''tu3.gif''
image [4] = ''tu4.gif''
number = Math.floor(Math.random() * image.length);
document.write("<BODY BACKGROUND="+image[number]+">");
</Script>
鼠标一碰就给颜色看的链接 在<body></body>之间加上如下代码:
<p onMouseMove="anniu()">你敢碰我,我就给点颜色你看!</p>
<Script Language = "VBScript">
sub anniu
document.fgColor=int(256*256*256*rnd)
end sub
</Script>
从天而降并有幻影效果的窗口
<head>
<Script language="JavaScript">
function move(x) {
if(self.moveBy){
self.moveBy (0,-800);
for(i = x; i > 0; i--)
{
self.moveBy(0,3);
}
for(j = 200; j > 0; j--){ //如果你认为窗口抖动厉害,就200换成个位数
self.moveBy(0,j);
self.moveBy(j,0);
self.moveBy(0,-j);
self.moveBy(-j,0);
}
}
}
</Scrip>
<body bgColor=#ffffff onload=move(280)>
</body>
</head>
表格的半透明显示效果 在<head></head>之间加上如下代码:
<style>
.alpha{filter: Alpha(Opacity=50)} //50表示50%的透明度
</style>
在<body></body>之间加上如下代码:
<table border="1" width="100" height="62" class="alpha" bgcolor="#F2A664" >
<tr>
<td width="100%" height="62">
<div align="center">很酷吧!</div>
</td>
</tr>
</table>
锁定状态栏文字防止显示地址
<body onmouseover="self.status=''文字'';return true">
禁止图片下载
在<body......>这里的最后加入:
oncontextmenu="return false" ondragstart="return false" onselectstart="return false" scroll="auto"
禁止缓存
<meta http-equiv="Expires" CONTENT="0">
<meta http-equiv="Cache-Control" CONTENT="no-cache">
<meta http-equiv="Pragma" CONTENT="no-cache">
加在HEAD里
使用包含页面
加密所包含页面地址,使用工具 htmlguardian5.3.5
目前功能最强的html代码加密软件,可以保护连接和html代码被盗。1.锁右键。2.禁鼠标圈选。3.不允许离线使用。4.密码保护。5.不显示状态栏url地址。6.全代码 或 局部代码保护。7.链接跟踪。8.禁止打印(IE5+)。9.压缩代码( 未加密前)。10.可加密*.html *.js *.asp *.vbs。11.两种不同加密算法。12.加密 frameset 结构。13.某些功能支持几个不同版本的浏览器。
下载flash我的三种方法:
--查看源文件,找出flash的绝对路径,复制,在flashget(或蚂蚁)中点任务
,然后点新建下载任务即可。
--在IE的临时文件夹Temporary Internet Files里把所有的东西都删掉,然后
刷新你想要下载flash的网页,即可得到你所要的flash
--使用外部软件,推荐使用Flash Catcher,安装后只需在你所要下载的flash上右键,save即可。
让IFRAME框架内的文档的背景透明
<iframe src="about:<body style=''background:transparent''>" allowtransparency></iframe>
进入页面后立即自动刷新?
<meta http-equiv="refresh" content="120;url=http://www.31u.net">
打开窗口即最大化
<script language="JavaScript">
<!-- Begin
self.moveTo(0,0)
self.resizeTo(screen.availWidth,screen.availHeight)
// End -->
</script>
能隐藏IFRAME的滚动条吗?我知道的三种方法:
1. 设置iframe scrolling="no"
2. 被包含页body应用overflow:hidden
3. 被包含页的body标签加scroll="no"
加入背景音乐
<bgsound src="mid/windblue[1].mid" loop="-1"> 只适用于IE
<embed src="music.mid" autostart="true" loop="true" hidden="true">
对Netscape ,IE 都适用
嵌入网页
<iframe name="tt" src="01a.html" width="450" height="287" scrolling="Auto" frameborder="0"></iframe>
跳转
<meta http-equiv="refresh" content="3;URL=list.htm">
滚动
<MARQUEE direction=up height=146 onmouseout=start() onmouseover=stop() scrollAmount=4>
</marquee>
细线分隔线
<hr noshade size=0 color=#C0C0C0>
过度方式
<meta http-equiv="Page-Exit" content="revealTrans(Duration=3,Transition=5)">
Duration的值为网页动态过渡的时间,单位为秒。
Transition是过渡方式,它的值为0到23,分别对应24种过渡方式。如下表:
0 盒状收缩 1 盒状放射
2 圆形收缩 3 圆形放射
4 由下往上 5 由上往下
6 从左至右 7 从右至左
8 垂直百叶窗 9 水平百叶窗
10 水平格状百叶窗 11垂直格状百叶窗
12 随意溶解 13从左右两端向中间展开
14从中间向左右两端展开 15从上下两端向中间展开
16从中间向上下两端展开 17 从右上角向左下角展开
18 从右下角向左上角展开 19 从左上角向右下角展开
20 从左下角向右上角展开 21 水平线状展开
22 垂直线状展开 23 随机产生一种过渡方式
如何控制横向和纵向滚动条的显隐?
<body style="overflow-y:hidden"> 去掉x轴
<body style="overflow-x:hidden"> 去掉y轴
<body scroll="no">不显
定义本网页关键字,可以在<Head></Head>中加入如下代码: <meta name="Keywords" content="china,enterprise,business,net">
Content 中所包含的就是关键字,你可以自行设置。
这里有个技巧,你可以重复某一个单词,这样可以提高自己网站的排行位置,如:
<meta name="Keywords" content="china,china,china,china">
IE5.0 的部分快捷键:
A:打开查找功能:Ctrl+F
关闭浏览器窗口:Ctrl+W
打开地址栏下拉列表框:F4
刷 新:F5
将当前Web页保存到收藏夹列表:Ctrl+D
打开当前 IE 窗口的一个拷贝:Ctrl+N
停止下载当前网页:Esc
光标迅速移动到网页的开头:Home
光标迅速移动到网页的尾部:End
打开新的地址键入窗口:Ctrl+O
打开收藏夹:Ctrl+I
打开历史记录文件夹:Ctrl+H
打开浏览器设定的默认主页:Alt+HOME
添加到收藏夹:
<a href="javascript:window.external.addFavorite(''http://链接'',''说明'');">添加到收藏夹</a>
设为首页:
<a href=# onclick=this.style.behavior=''url(#default#homepage)'';this.setHomePage (''http://链接'');>设为首页</a>
定制浏览器地址栏前的小图标:
A:在网页的<head></head>间加入以下语句
<link rel="shortcuticon" href="http://…/icon.ico">
即可。其中 icon.ico 为 16x16 的图标文件,
颜色不要超过 16 色。
把滚动条放在浏览器窗口的左边
A:在 <body> 中加 dir=RTL,即 <body dir=RTL>。
让背景图不滚动
IE浏览器支持一个 Body 属性 bgproperties,它可以让背景不滚动:
<Body Background="图片文件" bgproperties="fixed">
删除确认:
<input type="button" name="DEL" onclick="{if(confirm(''确认删除么?'')){location.href=''xxx.asp'';}return false;}" value="ON" >
隐藏状态栏中的链接地址:
<script language="javascript">
kstatus();
function kstatus(){
self.status="GBlog () ";
setTimeout("kstatus()",0);
}
</script>
自定义指定区域的文字大小:
<div id=zoom>sdrrrrrrrrrrrrrrrrrrrrrrrrrrrrr</div>
【<A href="javascript:doZoom(16)">大</A> <A href="javascript:doZoom(14)">中</A> <A href="javascript:doZoom(12)">小</A>】
<SCRIPT language=JavaScript>
function doZoom(size){
document.getElementById(''zoom'').style.fontSize=size+''px''
}
</script>
Input输入框文字效果:
<input type="text" value="123456" style="FONT-size:38px;color:red;font-family:arial black">
通过层来实现渐淡淡出
<script language="JavaScript1.2">
function makevisible(cur,which){
if (which==0)
cur.filters.alpha.opacity=100
else
cur.filters.alpha.opacity=50
}
</script>
<div style="width:200px;height:200px;filter:alpha(opacity=50);border:1px solid #000;background:#efefef" onMouseOver="makevisible(this,0)" onMouseOut="makevisible(this,1)">
ywicc.com
</div>
网页屏保
<script language="JavaScript">
function screensave(){
test.value++;
if(test.value==5){
test.style.display=''none'';
document.all[4].bgColor=''black'';
}
}
function screenopen(){
test.value=0;
test.style.display='''';
document.all[4].bgColor='''';
}
</script>
<body onkeydown="screenopen()" onmousemove="screenopen()" onload="setInterval(''screensave()'',1000)">
5 秒屏保<input id="test">
让标题动态
<script>
<!--
var tx = new Array (
"◇:::::::网页制作学习园地:::::::◇欢迎您!◇",
"◆欢迎大家光临网页制作学习园地网站!◆",
"◆大量供应网页制作教材,资料,源代码,网页制作软件,相关插件光盘!◆",
"◆最可怕的敌人,就是没有坚强的信念!◆",
"◆应该让别人的生活因为有了你的生存而更加美好!◆"
);
var txcount=5;
var i=1;
var wo=0;
var ud=1;
function animatetitle()
{
window.document.title=tx[wo].substr(0, i)+"_";
if (ud==0) i--;
if (ud==1) i++;
if (i==-1) {ud=1;i=0;wo++;wo=wo%txcount;}
if (i==tx[wo].length+10) {ud=0;i=tx[wo].length;}
// if (window.document.title.length < 20 ) window.document.title=window.document.title+"-";
// if (window.document.title.length == 20 ) window.document.title=window.document.title+"]";
// if (window.document.title.length == 21 ) setTimeout("window.document.title=''Animierte Seitentitel ''; ",1000);
parent.window.document.title=tx[wo].substr(0, i)+"_";
setTimeout("animatetitle()",100);
}
animatetitle();
// --></script><script language="JavaScript">
<!--
function MM_openBrWindow(theURL,winName,features) { //v2.0
window.open(theURL,winName,features);
}
//-->
</script>
隐去浏览器中当鼠标移到图片上跳出的工具栏
<img galleryimg="no">
或者
<head>
<meta http-equiv="imagetoolbar" content="no">
</head>
在form中只有input输入框的情况下...在这个input输入框中按enter进行提交表单
<form onsubmit="if(event.srcElement.name==''bb''){this.submit()}else{return false}">
<input name=a size=20>
<input type=button name=bb onclick="submit();">
</form>
删除确认
<input type="button" value="删除" onclick="{if(confirm(''确认删除么?'')){location.href=''aa.asp'';}return false;}">
或
<a href="http://www.31u.net/search.asp" onclick="{if(confirm(''确定删除吗?'')){return true;}return false;}">删除</a>
或
<a href="http://www.31u.net/search.asp" onclick="return confirm(''该删除操作将无法恢复!是否继续?'')">删除</a>
返回页面顶部:
javascript:window.scroll(0,0)
离开页面时弹出警告:
<BODY onbeforeunload="checkclose()">
<SCRIPT>
function checkclose(){
event.returnValue = "测试啊" //XXX可以改为任何文本信息也可以是空
}
</SCRIPT>
<a href="http://www.31u.net/search.asp">aa</a>
7:07 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | 计算机与 Internet
固定链接 关闭
http://spaces.msn.com/members/lionyang888/Blog/cns!1pegtqF_uRpLTqjlUYAIJKVQ!179.entry
WEB编程开发常用的代码
WEB编程开发常用的代码
2005-9-29 15:17:20 编辑:阿志 来源:来源网络
1. ASP与Access数据库连接:
dim conn,mdbfile
mdbfile=server.mappath("数据库名称.mdb")
set conn=server.createobject("adodb.connection")
''conn.open "driver={microsoft access driver (*.mdb)};uid=admin;pwd=数据库密码;dbq="&mdbfile
conn.open "Provider = Microsoft.Jet.OLEDB.4.0;Data Source = " & mdbfile
2. ASP与SQL数据库连接: dim conn
set conn=server.createobject("ADODB.connection")
con.open "PROVIDER=SQLOLEDB;DATA SOURCE=SQL服务器名称或IP地址;UID=sa;PWD=数据库密码;DATABASE=数据库名称;"
建立记录集对象: set rs=server.createobject("adodb.recordset")
rs.open SQL语句,conn,3,2
SQL常用命令使用方法:
数据记录筛选: sql="select * from 数据表 where 字段名=字段值 order by 字段名 "
sql="select * from 数据表 where 字段名 like ‘%字段值%‘ order by 字段名 "
sql="select top 10 * from 数据表 where 字段名 order by 字段名 "
sql="select * from 数据表 where 字段名 in (‘值1‘,‘值2‘,‘值3‘)"
sql="select * from 数据表 where 字段名 between 值1 and 值2"
更新数据记录: sql="update 数据表 set 字段名=字段值 where 条件表达式"
sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式"
删除数据记录: sql="delete from 数据表 where 条件表达式"
sql="delete from 数据表" (将数据表所有记录删除)
添加数据记录: sql="insert into 数据表 (字段1,字段2,字段3 …) valuess (值1,值2,值3 …)"
sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)
数据记录统计函数:
AVG(字段名) 得出一个表格栏平均值
COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(字段名) 取得一个表格栏最大的值
MIN(字段名) 取得一个表格栏最小的值
SUM(字段名) 把数据栏的值相加
引用以上函数的方法: sql="select sum(字段名) as 别名 from 数据表 where 条件表达式"
set rs=conn.excute(sql)
用 rs("别名") 获取统的计值,其它函数运用同上。
数据表的建立和删除: Create TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )
例:Create TABLE tab01(name varchar(50),datetime default now())
Drop TABLE 数据表名称 (永久性删除一个数据表)
记录集对象的方法:
rs.movenext 将记录指针从当前的位置向下移一行
rs.moveprevious 将记录指针从当前的位置向上移一行
rs.movefirst 将记录指针移到数据表第一行
rs.movelast 将记录指针移到数据表最后一行
rs.absoluteposition=N 将记录指针移到数据表第N行
rs.absolutepage=N 将记录指针移到第N页的第一行
rs.pagesize=N 设置每页为N条记录
rs.pagecount 根据 pagesize 的设置返回总页数
rs.recordcount 返回记录总数
rs.bof 返回记录指针是否超出数据表首端,true表示是,false为否
rs.eof 返回记录指针是否超出数据表末端,true表示是,false为否
rs.delete 删除当前记录,但记录指针不会向下移动
rs.addnew 添加记录到数据表末端
rs.update 更新数据表记录
判断所填数据是数字型
if not isNumeric(request("字段名称")) then
response.write "不是数字"
else
response.write "数字"
end if
页面执行时间:
<%startime = Timer()%>
.... ....
内容
... ...
结尾
<%
Dim Endtime
Endtime = Timer()
response.write "页面执行时间:<font color=red>"&FormatNumber((Endtime-Startime)*1000,5)&"</font> 毫秒"
%>
定义打开网页时起始窗口的大小
<script for="window" event="onload">
window.resizeTo(500,300)
</script>
随机数:
<%randomize%>
<%=(int(rnd()*n)+1)%>
查询数据时得到的记录关键字用红色显示:
replace(RS("字段X"),searchname,"<font color=#FF0000>" & searchname & "</font>")
通过asp的手段来检查来访者是否用了代理
<% if Request.ServerVariables("HTTP_X_FORWARDED_FOR")<>"" then
response.write "<font color=#FF0000>您通过了代理服务器,"& _
"真实的IP为"&Request.ServerVariables("HTTP_X_FORWARDED_FOR")
end if
%>
判断上一页的来源
request.servervariables("HTTP_REFERER")
javascript: document.referrer
清除缓存,重新加载页面
<%response.expires = 0
response.expiresabsolute = now() - 1
response.addHeader "pragma","no-cache"
response.addHeader "cache-control","private"
Response.cachecontrol = "no-cache"
%>
检索并删除数据库里的重复记录
conn.execute("delete from table where id not in (select distinct from table)")
文件删除函数 <%
''文件删除函数
function deletefile(filename)
if filename<>"" then
set fso=server.CreateObject("scripting.filesystemobject")
if fso.FileExists(filename) then
fso.DeleteFile filename
else
Response.Write "<script>alert(’该文件不存在’);</script>"
end if
end if
end function
strfile=server.MapPath("fileName")
deletefile(strfile)
%>
ASP字数计算函数 <%
Function WordCount(strInput)
Dim strTemp
strTemp = Replace(strInput, vbTab, " ")
strTemp = Replace(strTemp, vbCr, " ")
strTemp = Replace(strTemp, vbLf, " ")
'' 删除字首字尾空格
strTemp = Trim(strTemp)
'' 替换为一个空格
Do While InStr(1, strTemp, " ", 1) <> 0
strTemp = Replace(strTemp, " ", " ")
Loop
WordCount = UBound(Split(strTemp, " ", -1, 1)) +1
End Function
%>
全正则的检测IP是否合法的函数 function checkIP2(sIPAddress)
{
var exp=/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
var reg = sIPAddress.match(exp);
var ErrMsg="你输入的是一个非法的IP地址段!\nIP段为::xxx.xxx.xxx.xxx(xxx为0-255)!"
var Msg="你输入的是一个合法的IP地址段!"
if(reg==null)
{
alert(ErrMsg);
}
else
{
alert(reg);
}
}
关闭子窗口时刷新父窗口 在子窗口
<script language="javascript">
window.opener.location="父窗口页面"
window.close()
</script>
文本框输入限制:
<script>
function regInput(obj, reg, inputStr)
{
var docSel = document.selection.createRange()
if (docSel.parentElement().tagName != "INPUT") return false
oSel = docSel.duplicate()
oSel.text = ""
var srcRange = obj.createTextRange()
oSel.setEndPoint("StartToStart", srcRange)
var str = oSel.text + inputStr + srcRange.text.substr(oSel.text.length)
return reg.test(str)
}
</script>
小写英文:<xmp style= "display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[a-z]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[a-z]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[a-z]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
><br>
大写英文:<xmp style= "display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[A-Z]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[A-Z]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[A-Z]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled">
<br>
任意数字:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[0-9]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[0-9]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[0-9]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
><br>
限2位小数:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^\d*\.?\d{0,2}$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^\d*\.?\d{0,2}$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^\d*\.?\d{0,2}$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
> 如: 123.12<br>
日 期:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^\d{1,4}([-\/](\d{1,2}([-\/](\d{1,2})?)?)?)?$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^\d{1,4}([-\/](\d{1,2}([-\/](\d{1,2})?)?)?)?$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^\d{1,4}([-\/](\d{1,2}([-\/](\d{1,2})?)?)?)?$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
> 如: 2002-9-29<br>
任意中文:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[\u4E00-\u9FA5]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[\u4E00-\u9FA5]*$/, event.dataTransfer.getData(''Text''))"
><br>
部分英文:<xmp style="display:inline"> </xmp>
<input onkeypress = "return regInput(this, /^[a-e]*$/, String.fromCharCode(event.keyCode))"
onpaste = "return regInput(this, /^[a-e]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[a-e]*$/, event.dataTransfer.getData(''Text''))"
style="ime-mode:Disabled"
> 范围: a,b,c,d,e<br>
部分中文:<xmp style="display:inline"> </xmp>
<script language=javascript>
function checkChinese(oldLength, obj)
{
var oTR = window.document.selection.createRange()
var reg = /[^一二三四五六七八九十]/g
oTR.moveStart("character", -1*(obj.value.length-oldLength))
oTR.text = oTR.text.replace(reg, "")
}
</script>
<input onkeypress="return false" onkeydown="setTimeout(''checkChinese(''+this.value.length+'',''+this.uniqueID+'')'', 1)"
onpaste = "return regInput(this, /^[一二三四五六七八九十]*$/, window.clipboardData.getData(''Text''))"
ondrop = "return regInput(this, /^[一二三四五六七八九十]*$/, event.dataTransfer.getData(''Text''))"
> 范围: 一二三四五六七八九十<br>
[Ctrl+A 全选 Ctrl+C 复制]
不能点右键,不用CTRL+A,不能复制作!
<body oncontextmenu="window.event.returnValue=false"
onkeypress="window.event.returnValue=false"
onkeydown="window.event.returnValue=false"
onkeyup="window.event.returnValue=false"
ondragstart="window.event.returnValue=false"
onselectstart="event.returnValue=false">
</body>
显示状态拦固定文字:
放在body前
<base onmouseover="window.status=''这里是Goaler的Blog系统,欢迎访问'';return true">
用键盘打开网页 <script language=javascript>
document.onkeydown=gopage
var add="Admin/AddArticle.asp"
var logon="Admin/Logon.asp"
function gopage() {
if (event.keyCode==13) location=add
if (event.keyCode==38) location=logon
}
</script>
根据内容自动调整iframe高度 有时为了方便使用Iframe,但被潜入的页面长度不是固定的,显示滚动条不仅影响美观还对用户操作带来不便,自动调整高度可以解决这个问题。^_^
function f_frameStyleResize(targObj)
{
var targWin = targObj.parent.document.all[targObj.name];
if(targWin != null)
{
var HeightValue = targObj.document.body.scrollHeight
if(HeightValue < 600){HeightValue = 600} //不小于600
targWin.style.pixelHeight = HeightValue;
}
}
function f_iframeResize()
{
bLoadComplete = true;
f_frameStyleResize(self);
}
var bLoadComplete = false;
window.onload = f_iframeResize;
禁止页面正文内容被选取
<body oncontextmenu="return false" ondragstart="return false" onselectstart ="return false" onselect="document.selection.empty()" oncopy="document.selection.empty()" onbeforecopy="return
false"onmouseup="document.selection.empty()">
消除ie6自动出现的图像工具栏,设置 GALLERYIMG属性为false或no .
<IMG SRC="mypicture.jpg" HEIGHT="100px" WIDTH="100px" GALLERYIMG="no">
防止点击空链接时,页面往往重置到页首端。
代码“javascript:void(null)”代替原来的“#”标记
如何避免别人把你的网页放在框架中
<script language=“javascript”><!--if (self!=top){top.location=self.location;} -->< /script>
页面定时刷新
<meta http-equiv="Refresh" content="秒" >
页面定时转向新的地址
<meta http-equiv="refresh" content="秒;URL=url">
关闭窗口,这个是不会弹出提示直接关的:
把如下代码加入<body>区域中
<OBJECT id=closes type="application/x-oleobject" classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
<param name="Command" value="Close">
</object>
<script language="JavaScript">function shutwin(){closes.Click();return;}</script>
<a href="javascript:shutwin();">关闭本窗口</a>
有时候好不容易写出来的程序代码被别人抄去,心里一定不好受。这还是小事,但如果在我们的源代码中有一些不希望让别人知道的内容,比如密码、Action的指向等,这些一旦被人利用,那后果有时是不堪设想的。而网页加密就是我们现在需要解决的问题。下面就我在网页制作中的一些经验向大家介绍一些简单的防范方法。
禁止右键
看到这里大家一定会想,这招有很多人介绍过了,而且破解的方法也有很多。但我这里要说的是另一种方法,而且我试了很多方法都没有能破解。具体如下:
<html>
<head>
<script>
function stop(){
alert("试试能破解吗?");
return false;
}
document.oncontextmenu=stop;
</script>
<boyd>你可以按右键、shift+F10和右ctrl左边的那个键试试!看能不能解。^_^</body>
大家试试,看能不能破解!你可以将alert("试试能破解吗?");这句去掉,这样当按右键时就什么反应也没有了,就好像没有右键功能一样。
禁示查看源代码
我们已经禁了右键,但从"查看"菜单下的"源文件"中同样可以看到源代码,下面我们就来解决这个问题:
其实这只要使用一个含有<frame></frame>标记的网页便可以达到目的。
<frameset>
<frame src="你要保密的文件的URL">
</frameset>
这样当有人使用"查看"下的"源文件"的时候,看到的将是上面的那段代码,而你真正的文件又躲过一劫。
禁示另存为
通过上面的两步好像你的源代码已经安全了,但别忘了,别人还可以将你的页面保存下来,再慢慢分析。不过别担心,下面我们来解决这个问题。
在你要保密的网页中加入以下代码:
<noscript><iframe src="*.htm"></iframe></noscript>
彻底屏蔽右键方法。
<body oncontextmenu="return false">
双击页面后自动滚屏,单击后停止。
<SCRIPT language=JavaScript>
var currentpos,timer;
function initialize()
{ timer=setInterval("scrollwindow()",16); }
function sc(){
clearInterval(timer);
}
function scrollwindow()
{currentpos=document.body.scrollTop;
window.scroll(0,++currentpos);
if (currentpos != document.body.scrollTop)
sc();
}
document.onmousedown=sc
document.ondblclick=initialize
</script>
设定脚本出错能继续运行
<script language="javascript">
function KillError()
{
return false;
}
window.onerror=KillError;
</script>
7:00 | 固定链接 | 评论 (0) | 引用通告 (0) | 记录它 | 计算机与 Internet
固定链接 关闭
http://spaces.msn.com/members/lionyang888/Blog/cns!1pegtqF_uRpLTqjlUYAIJKVQ!178.entry
一些不常用的html代码
1. oncontextmenu="window.event.returnvalue=false" 将彻底屏蔽鼠标右键
<table border oncontextmenu=return(false)><td>no</table> 可用于Table
2. <body onselectstart="return false"> 取消选取、防止复制
3. onpaste="return false" 不准粘贴
4. oncopy="return false;" oncut="return false;" 防止复制
5. <link rel="Shortcut Icon" href="favicon.ico"> IE地址栏前换成自己的图标
6. <link rel="Bookmark" href="favicon.ico"> 可以在收藏夹中显示出你的图标
7. <input style="ime-mode:disabled"> 关闭输入法
8. 永远都会带着框架
<script language="javascript"><!--
if (window == top)top.location.href = "frames.htm"; //frames.htm为框架网页
// --></script>
9. 防止被人frame
<SCRIPT LANGUAGE=javascript><!--
if (top.location != self.location)top.location=self.location;
// --></SCRIPT>
10. <noscript><iframe src=*.html></iframe></noscript> 网页将不能被另存为
11. <input type=button value=查看网页源代码
onclick="window.location = ''view-source:''+ ''http://www.csdn.net/'">
12. 怎样通过asp的手段来检查来访者是否用了代理
<% if Request.ServerVariables("HTTP_X_FORWARDED_FOR")<>"" then
response.write "<font color=#FF0000>您通过了代理服务器,"& _
"真实的IP为"&Request.ServerVariables("HTTP_X_FORWARDED_FOR")
end if
%>
13. 取得控件的绝对位置
//javascript
<script language="javascript">
function getIE(e){
var t=e.offsetTop;
var l=e.offsetLeft;
while(e=e.offsetParent){
t+=e.offsetTop;
l+=e.offsetLeft;
}
alert("top="+t+"\nleft="+l);
}
</script>
//VBScript
<script language="VBScript"><!--
function getIE()
dim t,l,a,b
set a=document.all.img1
t=document.all.img1.offsetTop
l=document.all.img1.offsetLeft
while a.tagName<>"BODY"
set a = a.offsetParent
t=t+a.offsetTop
l=l+a.offsetLeft
wend
msgbox "top="&t&chr(13)&"left="&l,64,"得到控件的位置"
end function
--></script>
14. 光标是停在文本框文字的最后
<script language="javascript">
function cc()
{
var e = event.srcElement;
var r =e.createTextRange();
r.moveStart(''character'',e.value.length);
r.collapse(true);
r.select();
}
</script>
<input type=text name=text1 value="123" onfocus="cc()">
15. 判断上一页的来源
asp:
request.servervariables("HTTP_REFERER")
javascript:
document.referrer
16. 最小化、最大化、关闭窗口
<object id=hh1 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11">
<param name="Command" value="Minimize"></object>
<object id=hh2 classid="clsid:ADB880A6-D8FF-11CF-9377-00AA003B7A11">
<param name="Command" value="Maximize"></object>
<OBJECT id=hh3 classid="clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11">
<PARAM NAME="Command" value="Close"></OBJECT>
<input type=button value=最小化 onclick=hh1.Click()>
<input type=button value=最大化 onclick=hh2.Click()>
<input type=button value=关闭 onclick=hh3.Click()>
本例适用于IE
17.
<%
''定义数据库连接的一些常量
Const adOpenForwardOnly = 0 ''游标只向前浏览记录,不支持分页、Recordset、BookMark
Const adOpenKeyset = 1 ''键集游标,其他用户对记录说做的修改将反映到记录集中,但其他用户增加或删除记录不会反映到记录集中。支持分页、Recordset、BookMark
Const adOpenDynamic = 2 ''动态游标功能最强,但耗资源也最多。用户对记录说做的修改,增加或删除记录都将反映到记录集中。支持全功能浏览(ACCESS不支持)。
Const adOpenStatic = 3 ''静态游标,只是数据的一个快照,用户对记录说做的修改,增加或删除记录都不会反映到记录集中。支持向前或向后移动
Const adLockReadOnly = 1 ''锁定类型,默认的,只读,不能作任何修改
Const adLockPessimistic = 2 ''当编辑时立即锁定记录,最安全的方式
Const adLockOptimistic = 3 ''只有在调用Update方法时才锁定记录集,而在此前的其他操作仍可对当前记录进行更改、插入和删除等
Const adLockBatchOptimistic = 4 ''当编辑时记录不会被锁定,而更改、插入和删除是在批处理方式下完成的
Const adCmdText = &H0001
Const adCmdTable = &H0002
%>
18. 网页不会被缓存
HTM网页
<META HTTP-EQUIV="pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" CONTENT="no-cache, must-revalidate">
<META HTTP-EQUIV="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT">
或者<META HTTP-EQUIV="expires" CONTENT="0">
ASP网页
Response.Expires = -1
Response.ExpiresAbsolute = Now() - 1
Response.cachecontrol = "no-cache"
PHP网页
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
19. 检查一段字符串是否全由数字组成
<script language="javascript"><!--
function checkNum(str){return str.match(/\D/)==null}
alert(checkNum("1232142141"))
alert(checkNum("123214214a1"))
// --></script>
20. 获得一个窗口的大小
document.body.clientWidth,document.body.clientHeight
21. 怎么判断是否是字符
if (/[^\x00-\xff]/g.test(s)) alert("含有汉字");
else alert("全是字符");
22.TEXTAREA自适应文字行数的多少
<textarea rows=1 name=s1 cols=27 onpropertychange="this.style.posHeight=this.scrollHeight">
</textarea>
23. 日期减去天数等于第二个日期
<script language=javascript>
function cc(dd,dadd)
{
//可以加上错误处理
var a = new Date(dd)
a = a.valueOf()
a = a - dadd * 24 * 60 * 60 * 1000
a = new Date(a)
alert(a.getFullYear() + "年" + (a.getMonth() + 1) + "月" + a.getDate() + "日")
}
cc("12/23/2002",2)
</script>
24. 选择了哪一个Radio
<HTML><script language="vbscript">
function checkme()
for each ob in radio1
if ob.checked then window.alert ob.value
next
end function
</script><BODY>
<INPUT name="radio1" type="radio" value="style" checked>Style
<INPUT name="radio1" type="radio" value="barcode">Barcode
<INPUT type="button" value="check" onclick="checkme()">
</BODY></HTML>
25.获得本页url的request.servervariables("")集合
Response.Write "<TABLE border=1><!-- Table Header --><TR><TD><B>Variables</B></TD><TD><B>value</B></TD></TR>"
for each ob in Request.ServerVariables
Response.Write "<TR><TD>"&ob&"</TD><TD>"&Request.ServerVariables(ob)&"</TD></TR>"
next
Response.Write "</TABLE>"
26.
本机ip<%=request.servervariables("remote_addr")%>
服务器名<%=Request.ServerVariables("SERVER_NAME")%>
服务器IP<%=Request.ServerVariables("LOCAL_ADDR")%>
服务器端口<%=Request.ServerVariables("SERVER_PORT")%>
服务器时间<%=now%>
IIS版本<%=Request.ServerVariables"SERVER_SOFTWARE")%>
脚本超时时间<%=Server.ScriptTimeout%>
本文件路径<%=server.mappath(Request.ServerVariables("SCRIPT_NAME"))%>
服务器CPU数量<%=Request.ServerVariables("NUMBER_OF_PROCESSORS")%>
服务器解译引擎<%=ScriptEngine & "/"& ScriptEngineMajorVersion &"."&ScriptEngineMinorVersion&"."& ScriptEngineBuildVersion %>
服务器操作系统<%=Request.ServerVariables("OS")%>
27.ENTER键可以让光标移到下一个输入框
<input onkeydown="if(event.keyCode==13)event.keyCode=9">
28. 检测某个网站的链接速度:
把如下代码加入<body>区域中:
<script language=javascript>
tim=1
setInterval("tim++",100)
b=1
var autourl=new Array()
autourl[1]="www.njcatv.net"
autourl[2]="javacool.3322.net"
autourl[3]="www.sina.com.cn"
autourl[4]="www.nuaa.edu.cn"
autourl[5]="www.cctv.com"
function butt(){
document.write("<form name=autof>")
for(var i=1;i<autourl.length;i++)
document.write("<input type=text name=txt"+i+" size=10 value=测试中……> =》<input type=text name=url"+i+" size=40> =》<input type=button value=GO onclick=window.open(this.form.url"+i+".value)><br/>")
document.write("<input type=submit value=刷新></form>")
}
butt()
function auto(url){
document.forms[0]["url"+b].value=url
if(tim>200)
{document.forms[0]["txt"+b].value="链接超时"}
else
{document.forms[0]["txt"+b].value="时间"+tim/10+"秒"}
b++
}
function run(){for(var i=1;i<autourl.length;i++)document.write("<img src=http://"+autourl[i]+"/"+Math.random()+" width=1 height=1 onerror=auto(''http://";;;+autourl[i]+"'')>")}
run()</script>
29. 各种样式的光标
auto :标准光标
default :标准箭头
hand :手形光标
wait :等待光标
text :I形光标
vertical-text :水平I形光标
no-drop :不可拖动光标
not-allowed :无效光标
help :?帮助光标
all-scroll :三角方向标
move :移动标
crosshair :十字标
e-resize
n-resize
nw-resize
w-resize
s-resize
se-resize
sw-resize
1、 去掉IE的滚动条
有时候做好的网页明明没有超出窗口,可IE却偏偏给加上滚动条,这样看上去很不舒服,其实这也是可以通过一些小技巧避免的。具体如下:
<body style=”overflow-x:hidden”>…</body> //去掉X轴方向的滚动条
<body style=”overflow-y:hidden”>…</body> //去掉Y轴方向的滚动条
<body style=”overflow:hidden”>…</body> //去掉全部的滚动条
现在你看到的和你想像中的网页应该一样了吧,如果其中有什么不明白的地方可以参照注释中的说明。
2、 使网页中的复制无效
有方法防止网页被保存了(参见《你别看我的源代码》),可不可以也防止网页内容被复制呢?答案是当然可以。看看下面的例子你就会明白的。
<html>
<head>
<script language=”javascript”>
function nocopy() {
alert(“对不起,你不能非法复制本站内容”);
event.returnvalue=false;
}
</script>
</head>
<body oncopy=”nocopy()”>copyright by commander.</body>
</html>
这其实中是利用了document的一个oncopy事件,也就是说当发生复制事件时,弹出警告框,同时事件(event)的返回值为false使oncopy事件失效,从而达到防止复制的目的。
3、 用脚本控制浏览器
看到标题是不是有点不相信,那么试试下面的这几个例子吧!你一定会吃惊的。
在<body>和</body>之间加入如下代码:
<button onclick=”document.execCommand(‘open’)”>打开</button>
<button onclick=”document.execCommand(‘saveas’)”>另存为…</button>
<button onclick=”document.execCommand(‘print’)”>打印</button>
上面其实都是利用了document.execCommand()这个内置的函数,其参数为相应的浏览器命令,还有很多命令就留给大家自己发现吧!
4、 IFrame也可以编辑文字
有没有想过除了表单(<form>)之外还有其它的网页元素可以编辑文字呢?只要使用IFrame的隐藏的一个属性就可以使IFrame成为一个文本编辑器。
<html>
<body onload=”editer.document.designMode=’On’”>
<IFrame ID=”editer”></IFrame>
</body>
</html>
其中designMode属性表示IFrame的设计模式的状态(开/关),还在犹豫什么呢,快试试吧!
只要巧妙的利用这一特性就可以制作很多意想不到的效果。如果下面我们来做一个图片编辑器。
<html>
<body onload=”imgEditer.document.designMode=’On’;imgEditer.document.write(‘<img src=图片.gif>’)”>
<IFrame id=”imgEditer”></IFrame>
</body>
</html>
用鼠标点击图片是不是有新的发现,其实大家只要利用自己的想象和充分利用这个属性一定能做出更多的花样来,别忘了到时候有什么新的东东,告诉我一声呀!(Email:[email protected])
5、 打开硬盘
这是打开硬盘的另一种方法,把它写出来只是想告诉大家,要达到同一个目的有很多种方法,这里就是利用了表单的Action属性达到的,其实打开硬盘有很多种方法,只是这种不太被人们注意,所以这里就选择了这种方法。
<form action=file ://c|><input type=”submit” value=”打开C盘”></form>
Jun
1
说明:本文中所有程序均在Windows 2000 Server中文版 + SP2上编译运行无误
开发环境:.Net 框架1.0 Version 1.0.3705
一、ASP.NET虚拟主机存在的重大隐患
我曾经在WWW.BRINKSTER.COM申请了一个免费的ASP.NET空间,上传了两个程序,其中一个查看目录和文件的程序证明我的判断:ASP共享空间服务器存在的一个安全问题,在 ASP+ 共享空间服务器中依然存在并且变得更加难以防范!通过这个程序我可以浏览所有用户的ASP+程序,可以查看服务器的系统日志……,当然,如果我想删除什么的话也不会有什么问题。为了让大家更清楚地了解这一问题,我们有必要简单介绍一下ASP中就已经存在的这一问题。
ASP中常用的标准组件:FileSystemObject,这个组件为 ASP 提供了强大的文件系统访问能力,可以对服务器硬盘上的任何有权限的目录和文件进行读写、删除、改名等操作。FSO对象来自微软提供的脚本运行库scrrun.dll中。
使用下面的代码就可以在ASP中创建一个FSO对象:
Set fso = CreateObject("Scripting.FileSystemObject")
我们使用fso对象包含的属性和方法,如Drive、Drives、Folder、Floders、File、Files等对服务器的磁盘、目录和文件进行读、写、删除等操作。这一强大的文件系统访问能力给ASP共享空间提供者带来了严重的安全问题,很多ASP空间的管理员都删除此组件或将这个组件改名以避免用户使用这一标准组件。删除组件或组件改名确实是一个简单的方法并且也很有效,但是却使广大用户无法使用它的强大的功能。网络上还有一种看起来很美的方案,它允许用户使用 FileSystemObject 组件又不影响服务器的安全,即对每一个用户都设置一个独立的服务器用户和单个目录的操作权限。但是这种方法是有问题的。因为ASP和ASP.NET中在这方面的问题十分类似,所以我们将在ASP.NET的相应解决办法部分详加说明。
在ASP.NET中我们发现这一问题仍然存在,并且变得更加难以解决。这是因为.NET中关于系统IO操作的功能变得更加强大,而使这一问题更严重的是ASP.NET所具有的一项新功能,这就组件不需要象ASP那样必须要使用regsvr32来注册了,只需将Dll类库文件上传到bin目录下就可以直接使用了。这一功能确实给开发ASP.NET带来了很大的方便,但是却使我们在ASP中将此dll删除或者改名的解决方法失去效用了,防范此问题就变得更加复杂。在讨论解决方案之前,我们先来看一下怎么来实现上述的危险的功能。
二、文件系统操作示例
在我们编写代码之前,有必要了解一下我们需要用到的几个主要的类。这几个类都在System.IO名称空间下,System.IO 名称空间包含允许在数据流和文件上进行同步和异步读写的类。
在整个应用程序的开始部分我们需要了解一下服务器的系统信息,这就需要用到System.Environment类,该类提供有关当前环境和平台的信息以及操作它们的方法。我们通过System.Environment类可以得到系统的当前目录和系统目录,这可以使我们更快的发现几个关键的目录;我们还可以通过获取运行当前进程的用户名来帮助我们了解ASP.NET程序运行所使用的用户,进一步设置用户权限以避免这一安全问题。
我们还要使用System.IO名称空间的其他几个类是:
System.IO.Directory:提供用于创建、移动和枚举通过目录和子目录的静态方法的类
System.IO.File:提供用于创建、复制、删除、移动和打开文件的静态方法的类
System.IO.FileInfo:提供创建、复制、删除、移动和打开文件的实例方法的类
System.IO.StreamReader:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。
每个我们所使用的类的属性和方法的具体用法我们将以代码注释的方式在程序中加以说明。
System.IO名称空间在 .NET FRAMEWORK提供的mscorlib.dll中,在使用VS.Net编程之前需要将此Dll引用到此项目中。
我们所编写的程序都使用了Codebehind方式,即每一个aspx程序都有一个对应的aspx.cs程序,aspx程序中只是写与页面显示相关的代码,所有逻辑实现的代码都放在相应的aspx.cs文件中,这样就可以更好得做到显示与逻辑的分离。由于我们的目的不是讨论Codebehind技术,所以就不在对此多加讨论了。
在这篇文章里,我们只介绍几个主要的类及其关键方法的用法,详细程序请查看附带的源代码。
程序一:显示服务器的当前信息和全部逻辑驱动器的名称的程序listdrivers.aspx
主要方法1:我们使用 GetSysInf() 方法来得到服务器的当前环境和平台的信息
//获取系统信息的方法,此方法在listdrivers.aspx.cs文件中public void GetSysInf () {//获取操作系统类型qDrives = Environment.OSVersion.ToString();//获取系统文件夹qSystemDir = Environment.SystemDirectory.ToString();/*获取映射到进程上下文的物理内存量,通过这一内存映射量可以了解ASP.NET程序在运行时需要多少系统物理内存,有助于更好的规划我们的整个应用,因为物理内存量是以Byte为单位的,所以我们将此数值除以1024,可以得到单位为KB的物理内存量*/qMo = (Environment.WorkingSet/1024).ToString();//获取当前目录(即该进程从中启动的目录)的完全限定路径qCurDir = Environment.CurrentDirectory.ToString();//获取主机的网络域名qDomName = Environment.UserDomainName.ToString();//获取系统启动后经过的毫秒数qTick = Environment.TickCount;
//计算得到系统启动后经过的分钟数qTick /= 60000;//获取机器名qMachine = Environment.MachineName;//获取运行当前进程的用户名qUser = Environment.UserName;/*检索此计算机上格式为"<驱动器号>:"的逻辑驱动器的名称,返回字符串数组,这是下一步操作的关键所在*/achDrives = Directory.GetLogicalDrives();//获取此字符串数组的维数,确定有多少个逻辑驱动器nNumOfDrives = achDrives.Length;}
系统信息不需要进行操作,我们简单的用asp:Label将他们显示出来就行了。逻辑驱动器的个数在不同的服务器上是不定的,所以用不定长数组保存逻辑驱动器的名称,而且逻辑驱动器的名称也是我们下一步浏览目录和文件的基础,故我们采用了数据网格DataGrid来显示和处理它。
显示和处理逻辑驱动器名称的DataGrid的代码(代码在listdrivers.aspx文件):
<asp:DataGrid id="DriversGrid" runat="server" AutoGenerateColumns="false"><Columns><asp:BoundColumn HeaderText="ID" DataField="ID" /><asp:BoundColumn HeaderText="磁盘名" DataField="Drivers" /><asp:HyperLinkColumnHeaderText="详细信息" DataNavigateUrlField="Drivers" DataNavigateUrlFormatString="listdir.aspx?dir={0}" DataTextField="Detail" Target="_new" /></Columns></asp:DataGrid>
前两个BoundColumn列都是显示序号和实际逻辑驱动器名称的,需要说明的是第三列,我们在进入各个逻辑驱动器显示目录和文件之前需要将所选择的逻辑驱动器的名称传递到显示目录的文件去,所以需要一个特殊的超级链接行HyperLinkColumn,我们将DataNavigateUrlField设置为数据源中要绑定到 HyperLinkColumn 中的超级链接的 URL 的字段,在此即逻辑驱动器名称。然后将DataNavigateUrlFormatString设置为当 URL 数据绑定到数据源中的字段时,此HyperLinkColumn中的超级链接的 URL 的显示格式,即要链接到的下一级处理页面,在此为listdir.aspx?dir={用户点击行的逻辑驱动器名称}
创建数据源的代码(代码在listdrivers.aspx.cs文件中):
//通过此方法返回一个集合形式的数据视图DataViewICollection CreateDataSource() {//定义内存中的数据表DataTableDataTable dt = new DataTable();//定义DataTable中的一行数据DataRowDataRow dr;/*向DataTable中增加一个列,格式:DataColumn("Column", type)Column为数据列的名字,type为数据列的数据类型*/dt.Columns.Add(new DataColumn("ID", typeof(Int32)));dt.Columns.Add(new DataColumn("drivers", typeof(string)));dt.Columns.Add(new DataColumn("detail", typeof(string)));//使用for循环将逻辑驱动器的名称以行的形式添加到数据表DataTable中for (int i = 0; i < nNumOfDrives; i++) {//定义新行dr = dt.NewRow();//对行中每列进行赋值,注意要与上边定义的DataTable的行相对应dr[0] = i; //循环生成的序号dr[1] = achDrives.ToString(); //逻辑驱动器的名称dr[2] = "查看详情";//向DataTable中添加行dt.Rows.Add(dr);}//根据得到的DataTable生成自定义视图DataViewDataView dv = new DataView(dt);//返回得到的视图DataViewreturn dv;}
我们通过这个方法得到了一个包含所有我们需要的数据的数据视图DataView,我们只需要在此aspx页的Page_Load方法中将此数据视图绑定到DataGrid上就可以了。
数据绑定代码(代码在listdrivers.aspx.cs文件中):
/* 设置DataGrid的数据源DataSource为我们从CreateDataSource()方法得到的数据视图DataView */DriversGrid.DataSource = CreateDataSource();//将此DataGrid进行数据绑定DriversGrid.DataBind();
通过上边介绍的几种主要方法我们就实现了获取系统信息和显示所有逻辑驱动器名称的功能,并且可以通过相应的链接进入下一个显示目录和文件名的程序listdir.aspx显示该逻辑驱动器下的所有目录和文件。
程序二:显示目录中所有子目录和文件的程序listdir.aspx
目录下有子目录和文件两种形式,必须分别对待。我们调用此程序本身对子目录进行列表显示,而文件我们需要调用showfile.aspx程序对文件的属性和内容进行显示。并且两者还有不同的删除方法,所以我们在这里设置了两个DataGrid,两个DataTable,两个DataView,分别处理和显示目录和文件。
显示和处理目录和文件的DataGrid的代码(代码在listdir.aspx文件):
显示目录或文件的序号和名称的数据列类似于listdrivers.aspx程序中的相应代码,这里就不再重复了。对于子目录和文件分别有各自的处理页面,所以需要导航到两个不同的页面,对于子目录,我们继续使用listdir.aspx程序对其下的子目录和文件进行列表显示:
<asp:HyperLinkColumn DataNavigateUrlField="DirName"DataNavigateUrlFormatString="listdir.aspx?dir={0}"DataTextField="DirDetail" HeaderText="详细信息"Target="_new"/>
对于文件,我们使用showfile.aspx程序显示其属性和内容:
<asp:HyperLinkColumn DataNavigateUrlField="FileName"DataNavigateUrlFormatString="showfile.aspx?file={0}" DataTextField="FileDetail" HeaderText="详细信息" Target="_new" />
在两个DataGrid(DirGrid,FileGrid)中我们分别设置了两个HyperLinkColumn列来导航到不同的处理页面。
在两个DataGrid中我们都使用了一个删除的按钮列:
<asp:ButtonColumn HeaderText="删除" Text="删除" CommandName="Delete"/>
由于添加、更新、删除功能列都是DataGrid的默认模板列,所以可以在Vs.net中通过DataGrid的属性生成器自动添加此列。
获取上一页面所传递来的参数的代码:
因为在下面产生数据源的方法中需要使用由上一个页面传递过来的参数来确定目录和文件的名称,所以在页面的Page_Load方法里使用了下列代码:
strDir2List = Request.QueryString["dir"];
字符串strDir2List即传过来的目录名或文件名。
因为我们使用了两个DateGrid,就需要进行两次数据绑定,就有两个不同的生成数据源的方法。
生成目录数据网格(DirGrid)数据源的方法:
//通过此方法返回一个集合形式的数据视图DataView,用来初始化子目录的DataGridICollection CreateDataSourceDir() {dtDir = new DataTable();DataRow dr;//向DataTable中添加新的数据列,共四列dtDir.Columns.Add(new DataColumn("DirID", typeof(Int32)));dtDir.Columns.Add(new DataColumn("DirName", typeof(string)));dtDir.Columns.Add(new DataColumn("DelDir", typeof(string)));dtDir.Columns.Add(new DataColumn("DirDetail", typeof(string))); //根据传入的参数(目录名)得到此目录下所有子目录名的字符串数组string [] DirEntries = Directory.GetDirectories(strDir2List);//使用foreach循环可以对未知长度的数组进行遍历循环foreach(string DirName in DirEntries){dr = dtDir.NewRow();dr[0] = i;//序号dr[1] = DirName;//文件夹名称 dr[3] = "删除";dr[3] = "查看详情";dtDir.Rows.Add(dr);i++; }DataView dvDir = new DataView(dtDir);//返回得到的数据视图return dvDir;}生成文件数据网格(FileGrid)数据源的方法://通过此方法返回一个集合形式的数据视图DataView,用来初始化文件的DataGridICollection CreateDataSourceFile() {dtFile = new DataTable();DataRow dr;dtFile.Columns.Add(new DataColumn("FileID", typeof(Int32)));dtFile.Columns.Add(new DataColumn("FileName", typeof(string)));dtFile.Columns.Add(new DataColumn("DelFile", typeof(string)));dtFile.Columns.Add(new DataColumn("FileDetail", typeof(string))); //根据传入的参数(目录名)得到此目录下所有文件名的字符串数组string [] FileEntries = Directory.GetFiles(strDir2List);foreach(string FileName in FileEntries){dr = dtFile.NewRow();dr[0] = i;dr[1] = FileName; dr[2] = "删除";dr[3] = "查看详情";dtFile.Rows.Add(dr);i++;}dvFile = new DataView(dtFile);return dvFile;}
我们编程实现了两个DataSource只需在页面的Page_Load方法里对两个DataGrid进行数据绑定即可将得到的DataTable中的数据显示在aspx页面的DataGrid上。
数据绑定代码:
//对子目录数据列表DirGrid进行数据源定义和数据绑定DirGrid.DataSource = CreateDataSourceDir();DirGrid.DataBind(); //对文件数据列表FileGrid进行数据源定义和数据绑定FileGrid.DataSource = CreateDataSourceFile();FileGrid.DataBind();
通过我们上边介绍的主要方法,我们实现了对某个逻辑驱动器或目录中的所有子目录和文件进行了列表显示,并且可以根据显示结果更进一步的浏览子目录或者查看文件的属性和内容提要。浏览子目录仍然是通过listdir.aspx这个程序,没有任何子目录级别要求,没有目录深度限制。
删除子目录和文件的主要方法和代码:
在删除子目录时,我们需要用到Directory.Delete (string,bool)方法,此方法有两种:
1.public static void Delete(string);
从指定路径删除空目录。
2.public static void Delete(string, boolean);
删除指定的目录并(如果指示)删除该目录中的任何子目录,将boolean设置为true的话,则删除此目录下的所有子目录和文件,否则将boolean设置为false。
在这里我们使用了第二种方法,如果选择删除的话,将删除此目录下的所有子目录和文件。
注意:Directory 类的所有方法都是静态的,因而无需具有目录Directory的实例就可被调用。
/*实现删除子目录的方法,此方法为VS.NET自动添加,注意DataGridCommandEventArgs e为DirGrid中 CommandName="Delete" 的ButtonColumn的事件,通过此事件,我们可以得到是那一行的ButtonColumn按钮列被点击,进而确定我们需要删除的子目录的名称*/private void DirGrid_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e){/*定义一个单元格,e.Item为此事件所发生行的所有项目,e.Item.Cells[1]为整个行的第二个单元格的内容,在此DataGrid中为子目录的名称*/TableCell ItemCell = e.Item.Cells[1];//得到此子目录的名称的字符串string item = ItemCell.Text;//删除此子目录Directory.Delete(item,true);//删除后进行数据绑定以更新数据列表DirGrid.DataBind();}
在删除文件时,我们需要用到File.Delete(string path);
注意:File 类的所有方法都是静态的,因而无需具有目录的实例就可被调用。
private void FileGrid_DeleteCommand(object source,System.Web.UI.WebControls.DataGridCommandEventArgs e) {TableCell ItemCell = e.Item.Cells[1];//得到此文件名称的字符串string item = ItemCell.Text;//删除此文件File.Delete(item);//删除后进行数据绑定以更新数据列表DirGrid.DataBind();}
通过上边的主要方法我们在页面上实现了一个删除某一个子目录或者文件的功能,此功能在测试时需要慎重使用,一旦删除无法通过常规方法恢复。其他如目录或文件改名、修改内容等方法都可以在此程序基础上添加相应的功能,实现方法也很简单。各位爱好者可以通过添加相应功能,使之扩充为一个基于Web的服务器文件管理系统。我们也可以由此看到这个程序的危害性,一个没有对此安全隐患采取防范措施的服务器的文件系统就都暴露在了使用此程序的用户面前。
程序三:显示文件属性和内容的程序showfile.aspx
在显示属性和内容时需要用到的两个主要的类:
System.IO.FileInfo:提供创建、复制、删除、移动和打开文件的实例方法,并且帮助创建 FileStream 对象。
System.IO.StreamReader:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。除非另外指定,StreamReader的默认编码为 UTF-8,而不是当前系统的 ANSI 代码页。UTF-8 可以正确处理 Unicode 字符并在操作系统的本地化版本上提供一致的结果。
Showfile.aspx页面主要代码:
<asp:Label id="FileDetail" runat="server"/>
我们只是将文件的属性信息和部分内容显示在此Label上。所以没有其他复杂的代码。
获取文件信息和内容的主要代码都在Page_Load方法中(代码在showfile.aspx.cs文件中):
//接收传入的参数,确定需要操作的文件名称strFile2Show = Request.QueryString["file"];//根据文件名实例化一个FileInfo对象FileInfo fi = new FileInfo(strFile2Show);FileDetail.Text = "文件名:";FileDetail.Text += strFile2Show+"<br>";FileDetail.Text += "文件大小";//获得文件的大小,然后变换单位为KBFileDetail.Text += (fi.Length/1024).ToString()+"K<br>";FileDetail.Text += "创建文件时间:";//获得文件的创建日期FileDetail.Text += fi.CreationTime.ToString();FileDetail.Text += "上次访问时间:";//获得文件的上次访问日期FileDetail.Text += fi.LastAccessTime.ToString()+"<br>";FileDetail.Text += "上次写入时间:";//获得文件的上次写入日期FileDetail.Text += fi.LastWriteTime.ToString()+"<br>";//实例化一个StreamReader对象,用于读取此FileInfo的内容StreamReader FileReader = fi.OpenText();//定义一个长度为1000的字符数组作为缓冲区char[] theBuffer = new char[1000];/*ReadBlock方法:从当前流中读取最大数量的字符并从索引开始将该数据写入缓冲区。参数:char[] buffer:方法返回时,包含指定的字符数组int index:buffer 中开始写入的位置int count:最多读取的字符数*/int nRead = FileReader.ReadBlock(theBuffer,0,1000);FileDetail.Text += new String(theBuffer,0,nRead);//关闭此 StreamReader 并释放与之关联的所有系统资源FileReader.Close();
到目前为止,我们实现了一个简单的web页面的服务器磁盘管理应用程序,可以查看、删除目录和文件。如果需要修改文件、新建文件和文件夹等功能,只需稍作修改,添加上相应的代码就可以。由于我们只是通过这个程序说明服务器中存在的安全隐患,所以在这里就不再实现这些功能了。
通过这三个简单的程序,我想大家已经能够清楚的认识到这一漏洞的危害性了,如果我们不加防范的话,其他用户的程序就能被恶意使用此功能的用户查看、删除,服务器的系统日志、系统文件也没有任何安全可言了。
解决方案
将FSO组件和删除或改名的方式我们不再过多的加以说明了,这一类的解决方法网络上已经有很多文章介绍了。
另外还有一种关于ASP的FSO组件漏洞的相应解决方案,即根据用户设置权限。在IIS里,可以设置每个站点的匿名访问所使用的帐号,默认为IUSR_ HostName,这一方法的原理就是针对每一个共享主机用户分别设置一个Windows帐号,如IUSR_HostName1,IUSR_ HostName 2等,然后将每一个用户限制在各自的Web目录下。
我们仔细的研究一下这种方案,可以发现这个方案无法真正实现安全。因为系统运行ASP时并不是使用的IUSR_ HostName帐号,而是IWAM_ HostName帐号,就象在ASP.NET中使用的用户ASPNET一样。也就是说每个ASP程序所拥有的权限并不是IUSR_ HostName的权限,而是IWAM_HostName用户的权限。这样的方法无法真正的将每个共享主机用户的文件系统访问权限限制在各自的虚拟站点中,每个用户仍然可以访问别人的代码。所以这种方法在ASP.NET中无法真正实现用户之间的安全性。
在ASP.NET中相应的运行ASP.NET程序的帐号为ASPNET,和上面所说的ASP中的解决方案类似,我们只能限制此用户不能访问系统目录等其他目录,但是无法防止用户访问其他共享主机用户的程序代码,无法从根本上杜绝这种问题。
那么,有没有真正的解决方案了呢?
有!这就是.NET Framework 的新特性――代码访问安全性
为了更好的理解这一问题的解决方法,我们需要先介绍一下.NET Framework的安全机制。然后再结合我们的实际问题来讨论解决方案。
为了解决安全问题,.NET Framework提供了一种称为代码访问安全性的安全机制。代码访问安全性允许根据代码的来源和代码的标识等属性将代码设置为不同级别的信任代码,同时还详细定义了不同级别的对代码的信任,从而可以详细的对代码设置各自的权限而不是将最大权限赋给所有的代码。使用代码访问安全性,可以减小恶意代码或各种错误的代码带来的严重的系统安全性问题的可能性。您可以设置允许代码执行的一组操作,同样可以设置永远不允许代码执行的一组操作。
实现代码访问安全性的基础就是JIT(运行时编译)和IL(中间代码)。所以所有以公共语言运行库为目标的托管代码都会受益于代码访问安全性。非托管代码则无法完全使用代码访问安全性。
下面我们将介绍一下代码访问安全性实现的各种功能:
代码访问安全性是控制代码对受保护资源和操作的访问权限的一种机制。在 .NET Framework中,代码访问安全性执行下列功能:
· 定义权限和权限集,它们表示访问各种系统资源的权限。
· 使管理员能够通过将权限集与代码组关联来配置安全策略。
· 使代码能够请求运行所需权限以及其他一些有用的权限,以及指定代码绝对不能拥有哪些权限。
· 根据代码请求的权限和安全策略允许的操作,向加载的每个程序集授予权限。
· 使代码能够要求其调用方拥有特定的权限。
· 使代码能够要求其调用方拥有数字签名,从而只允许特定组织或特定站点的调用方来调用受保护的代码。
· 通过将调用堆栈上每个调用方所授予的权限与调用方必须拥有的权限相比较,加强运行时对代码的限制。
为了确定是否已授予代码相应的权限,.NET运行库的安全系统将遍历整个调用堆栈,将每个调用方所授予的权限与目前要求的权限相比较。如果调用堆栈中的任何调用方没有要求的权限,则会引发安全性异常,并会拒绝访问和相应的操作。堆栈步旨在防止引诱攻击;在这种攻击中,受信程度较低的代码调用高度信任的代码,并使用高度信任的代码执行未经授权的操作。在运行时要求所有调用方都拥有权限将影响性能,但对防止代码遭受攻击至关重要。若要优化性能,可以使代码执行较少的堆栈步;但是,任何时候这样做时均必须确保不会暴露安全缺陷。
还存在另外一种代码访问安全性的常见用途,即应用程序将控件从网络 Web 站点直接下载到客户端,这种方式的代码安全性也是可以在客户端进行设置的,根据签名等数据权限证书来确定是不是可以允许下载的控件运行。这种方法类似于ActiveX的安全性设置,但是比之在设置权限更加详细和强大。同JAVA APPLET的沙箱安全机制相比,.NET 的客户端控件可以在本地简单设置后访问客户端的各种资源。由于这一方面的用途不是我们的重点,所以我们在这里就不再更详细的讨论其用途及其实现原理了。
下面我们就谈谈如何应用这一安全特性来解决ASP.NET中存在的系统安全漏洞。由于我们介绍的系统是共享主机,所以有其特殊性,即系统管理员无法事先给所有的代码赋予相应的权限,因为每个用户都可能有各种权限要求,并且这些要求特殊权力的代码在使用中都可能出现的,所以在权限管理上随时都有各种要求。
因此在权限设置方面,不仅仅是管理员设置,也包括了各个共享主机用户的权限请求,这也正是安全代码机制的一个重要部分。
请求权限是您让运行库知道代码执行有哪些操作权限的方法。通过将属性(声明式语法)放到代码的程序级范围来为程序集请求权限。
请求内置权限的代码示例:
//The attribute is placed on the assembly level.using System.Security.Permissions;[assembly:PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
将此段代码放在程序的开始部分(namespace声明之前),在编译时就会将请求的权限存储在程序集清单中。加载时,运行库检查权限请求,并应用安全策略规则来确定授予程序集哪些权限。
虽然我们编写的大部分代码都没有请求权限,其实不管是共享主机形式还是独立服务器形式都应该请求权限,这是因为请求权限有助于确保只将代码需要的权限授予代码。如果没有授予代码额外权限,即使某些恶意代码想利用您的代码来进行安全性破坏,它也无法操作没有赋给您自己代码相应权限的额外系统资源。您只应该请求代码需要的那些权限,而不应请求更多权限。
代码请求权限之后,系统管理员可以使用"权限查看"工具 (Permview.exe,位于您的.NET Framework的目录的bin目录下) 来检查您的程序集并根据其他条件来设置安全策略以决定是否给您的代码所请求的相应权限。如果您不显式地在代码中请求应用程序需要的权限,那么管理员将很难管理您的应用程序。在权限管理严格的主机上,将无法实现您的代码所要求的功能。
请求权限会通知运行库应用程序正常运行需要哪些权限,或具体不需要哪些权限。在.NET Framework安装后的默认状态下,所有代码都是FullTrust(完全信任)的。这时是不需要申请任何权限的,但是管理员一旦修改了代码安全,我们使用的磁盘访问就要受到限制了,这是就需要申请相应的权限了。我们上边介绍的文件管理代码就需要具有本地硬盘读写操作的能力,则应用程序必须拥有 FileIOPermission。如果代码不请求 FileIOPermission,在本地安全设置不允许应用程序拥有此权限的主机上,在应用程序尝试磁盘操作时就会引发安全性异常。即使应用程序能够处理此异常,也不会允许它操作磁盘。当然,如果您的代码不访问受保护的资源或执行受保护的操作,则不必请求任何权限。例如,如果代码只根据向它传递的输入来计算结果而不使用任何资源,则不必请求权限。如果您的代码访问受保护的资源但未请求必要的权限,则仍可能允许它执行,但如果它尝试访问某种资源而它又没有必要的权限,则可能在执行过程中失败。
系统管理员在得到了用户的权限申请后,可以根据情况考虑是否赋予用户相应的权限,在这里我们来看一下相应代码权限设置的具体方法。
在我们安装成功.NET Framework之后,在Windows 2000 Server的管理工具里多了两项管理工具: Microsoft .NET Framework Configration和Microsoft .NET Framework Wizards。这两种管理工具要实现的功能差不多,只不过Microsoft .NET Framework Wizards是通过向导方式设置,如果您对于.NET Framewrk的安全性操作不是很熟悉的话,可以使用向导根据系统提示一步步的来设置相关的权限。

Microsoft .NET Framework Wizards界面

Microsoft .NET Framework Wizards界面
使用Microsoft .NET Framework Wizards可以简单的设置.NET Framework的权限。但是我们为了更好的管理各个代码的权限,还是使用Microsoft .NET Framework Configuration来详细的设置我们所需的权限。

(Microsoft .NET Framework Configuration主界面)
在Microsoft .NET Framework Configuration中可以设置所有关于.NET Framework的属性。
点击我的电脑,打开下拉菜单,我们可以看到程序集缓存、已配置程序集、远程处理服务、运行库安全策略、应用程序等五项。运行库安全策略设置是我们这篇文章的重点。
我们可以先查看一下程序集缓存,在这里我们可以看到所有的全局程序集缓存,全局程序集缓存中存储了专门指定给由计算机中若干应用程序共享的程序集。在这里我们可以发现我们可以使用的所有的程序集,同时也可以添加和删除某些程序集。详细操作请参见.NET Framework SDK文档。
我们在这里主要讨论的是运行库安全策略。在此策略中,按层次结构由高到低分为四个级别,即:企业、计算机、用户、应用程序。在计算权限授予时,运行库从该层次结构的顶部开始,然后向下进行计算。较低的策略级别不能对在较高级别上授予的权限进行增加,但是可以使权限减少。这就是说如果我们将计算机策略设置为较小的权限时,可以不必更改企业策略就可以使设置的权限生效,也就是说权限检查的顺序是从低级别到高级别,只有在低级别中不存在的设置才会检查上一级的设置。默认情况下,用户策略和应用程序域策略的限制性小于计算机策略和企业级策略。大部分默认策略存在于计算机级别。所以我们需要将默认安装的主机的权限在计算机级别上进行修改,修改的内容根据主机是不是共享主机,主机应用的其他不明代码的可能性来设置。如果是我们讨论的共享主机的话,在计算机级别上就尽量将权限设的小一些,为了避免我们讨论的文件系统安全问题,一定要注意权限中的本地磁盘访问权限。
我们打开计算机策略设置可以发现几个默认的代码组、权限集和策略程序集。
根据需要,我们可以添加代码组和自定义的权限集。
在添加代码组的时候可以选择几种条件,主要的条件类型:默认为All Code、应用程序目录、哈希、强名称、作者、站点等。
对于我们所要讨论的共享主机,我们需要将My_Computer_Zone下的All Code的权限更改为不能进行磁盘读写,在更改之前,我们需要先定义一个权限集。这一权限集的作用就是将我们需要点击权限集,右键快捷菜单中选择新建,会出现一个创建权限集的窗口,这里需要给我们新建的权限集命名。下一步就是将单个权限分配给权限集。如下图所示。

在这里我们可以给这个新建的权限集赋予一个的系统权限,如上图所示,可用的权限包括:目录服务、DNS、事件日志、环境变量、文件IO、OLEDB数据库操作、注册表等等。我们主要要说明的是文件IO操作,其他的权限操作可以根据自己的需求来设置。这里我们就不再说明了。
在文件IO的权限设置中我们可以自定义针对每一个目录的权限,这里包括读、写、追加、路径盘等操作,在这里我们可以将我们需要的目录权限添加到列表中。因为我们是利用这一权限使所有没有配置权限的代码不可以进行文件IO操作,所以我们不强文件IO添加到分配的权限中。
新建了这一权限集后,我们更改一下默认设置,即将All Code的权限设置为此新建的权限集,也就是说所有没有在此定义代码都不能访问文件IO系统。
这里需要注意一件事情,因为Microsoft .NET Framework Configuration本身也需要文件IO权限,如果没有单独分配给Configuration一个文件IO操作权限的话,那么您就不能再次使用Configuration来设置权限了,只能重新安装.NET Framework了。所以我们需要将FullTrust权限分配给Configuration所使用的Dll,即mscorcfg.dll。在添加时,成员条件可以选择强名称,使用"导入",到winnt/window .net/framework/versionnumber/下选择mscorcfg.dll。如果需要运行其他配置程序,还需要设置相应的权限,这些系统程序一般都在系统程序集缓存中。
这样我们就完成了一个简单的设置,可以防止任何未经验证的代码访问文件IO系统。这样就从根本上防止了磁盘恶意操作。
如果您今后需要利用这一功能或者有共享主机用户需要使用文件IO功能,那么您可以在Microsoft .NET Framework Configuration中将其加入代码,如果不能使其使用其他功能,可以仅仅设置一个只具有文件IO权限的权限集。如果是共享主机用户您还可以给他分配直接到其所使用的目录的全部读写权限,对于他的日志文档,您可以将读功能分配给用户。通过上边新建权限集时我们可以发现:权限集可以规定到每一个目录的读写权限,所以可以将用户锁定于其可以使用的目录中。当然对于共享主机提供商来说,最好的方法就是自己实现这些功能,然后配置权限系统使用户使用共享主机提供商的程序来实现他们的正常操作,而避免了恶意文件操作。
需要注意的是如果分配给每一个单独的程序相应的权限时,我们最好使用强名称这一方式或者其他的可验证方式,强名称由程序集的标识--其简单文本名称、版本号和区域性信息(如果提供)--加上公钥和数字签名组成。这就需要我们使用Sn.exe 来设置密钥、签名和签名验证。强名称保证了程序是开发人员开发的并且没有被改动。
在进行上面的设置之后,管理员可以根据用户的各种需求来设置不同的代码集和权限集。
我们已经简单的介绍了一下ASP.NET中关于文件IO系统的漏洞的防治方法,这一方法有些繁琐,但是却可以从根本上杜绝一些漏洞,由于.NET的JIT(运行时编译)和IL(中间语言),.NET可以在程序编译时检查程序的安全性设置,所以能从根本上防止一些非法访问。.NET的代码安全性的内容很全面,我们讨论的只是很少的一部分,更多的功能需要大家共同来探索、学习。
开发环境:.Net 框架1.0 Version 1.0.3705
一、ASP.NET虚拟主机存在的重大隐患
我曾经在WWW.BRINKSTER.COM申请了一个免费的ASP.NET空间,上传了两个程序,其中一个查看目录和文件的程序证明我的判断:ASP共享空间服务器存在的一个安全问题,在 ASP+ 共享空间服务器中依然存在并且变得更加难以防范!通过这个程序我可以浏览所有用户的ASP+程序,可以查看服务器的系统日志……,当然,如果我想删除什么的话也不会有什么问题。为了让大家更清楚地了解这一问题,我们有必要简单介绍一下ASP中就已经存在的这一问题。
ASP中常用的标准组件:FileSystemObject,这个组件为 ASP 提供了强大的文件系统访问能力,可以对服务器硬盘上的任何有权限的目录和文件进行读写、删除、改名等操作。FSO对象来自微软提供的脚本运行库scrrun.dll中。
使用下面的代码就可以在ASP中创建一个FSO对象:
Set fso = CreateObject("Scripting.FileSystemObject")
我们使用fso对象包含的属性和方法,如Drive、Drives、Folder、Floders、File、Files等对服务器的磁盘、目录和文件进行读、写、删除等操作。这一强大的文件系统访问能力给ASP共享空间提供者带来了严重的安全问题,很多ASP空间的管理员都删除此组件或将这个组件改名以避免用户使用这一标准组件。删除组件或组件改名确实是一个简单的方法并且也很有效,但是却使广大用户无法使用它的强大的功能。网络上还有一种看起来很美的方案,它允许用户使用 FileSystemObject 组件又不影响服务器的安全,即对每一个用户都设置一个独立的服务器用户和单个目录的操作权限。但是这种方法是有问题的。因为ASP和ASP.NET中在这方面的问题十分类似,所以我们将在ASP.NET的相应解决办法部分详加说明。
在ASP.NET中我们发现这一问题仍然存在,并且变得更加难以解决。这是因为.NET中关于系统IO操作的功能变得更加强大,而使这一问题更严重的是ASP.NET所具有的一项新功能,这就组件不需要象ASP那样必须要使用regsvr32来注册了,只需将Dll类库文件上传到bin目录下就可以直接使用了。这一功能确实给开发ASP.NET带来了很大的方便,但是却使我们在ASP中将此dll删除或者改名的解决方法失去效用了,防范此问题就变得更加复杂。在讨论解决方案之前,我们先来看一下怎么来实现上述的危险的功能。
二、文件系统操作示例
在我们编写代码之前,有必要了解一下我们需要用到的几个主要的类。这几个类都在System.IO名称空间下,System.IO 名称空间包含允许在数据流和文件上进行同步和异步读写的类。
在整个应用程序的开始部分我们需要了解一下服务器的系统信息,这就需要用到System.Environment类,该类提供有关当前环境和平台的信息以及操作它们的方法。我们通过System.Environment类可以得到系统的当前目录和系统目录,这可以使我们更快的发现几个关键的目录;我们还可以通过获取运行当前进程的用户名来帮助我们了解ASP.NET程序运行所使用的用户,进一步设置用户权限以避免这一安全问题。
我们还要使用System.IO名称空间的其他几个类是:
System.IO.Directory:提供用于创建、移动和枚举通过目录和子目录的静态方法的类
System.IO.File:提供用于创建、复制、删除、移动和打开文件的静态方法的类
System.IO.FileInfo:提供创建、复制、删除、移动和打开文件的实例方法的类
System.IO.StreamReader:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。
每个我们所使用的类的属性和方法的具体用法我们将以代码注释的方式在程序中加以说明。
System.IO名称空间在 .NET FRAMEWORK提供的mscorlib.dll中,在使用VS.Net编程之前需要将此Dll引用到此项目中。
我们所编写的程序都使用了Codebehind方式,即每一个aspx程序都有一个对应的aspx.cs程序,aspx程序中只是写与页面显示相关的代码,所有逻辑实现的代码都放在相应的aspx.cs文件中,这样就可以更好得做到显示与逻辑的分离。由于我们的目的不是讨论Codebehind技术,所以就不在对此多加讨论了。
在这篇文章里,我们只介绍几个主要的类及其关键方法的用法,详细程序请查看附带的源代码。
程序一:显示服务器的当前信息和全部逻辑驱动器的名称的程序listdrivers.aspx
主要方法1:我们使用 GetSysInf() 方法来得到服务器的当前环境和平台的信息
//获取系统信息的方法,此方法在listdrivers.aspx.cs文件中public void GetSysInf () {//获取操作系统类型qDrives = Environment.OSVersion.ToString();//获取系统文件夹qSystemDir = Environment.SystemDirectory.ToString();/*获取映射到进程上下文的物理内存量,通过这一内存映射量可以了解ASP.NET程序在运行时需要多少系统物理内存,有助于更好的规划我们的整个应用,因为物理内存量是以Byte为单位的,所以我们将此数值除以1024,可以得到单位为KB的物理内存量*/qMo = (Environment.WorkingSet/1024).ToString();//获取当前目录(即该进程从中启动的目录)的完全限定路径qCurDir = Environment.CurrentDirectory.ToString();//获取主机的网络域名qDomName = Environment.UserDomainName.ToString();//获取系统启动后经过的毫秒数qTick = Environment.TickCount;
//计算得到系统启动后经过的分钟数qTick /= 60000;//获取机器名qMachine = Environment.MachineName;//获取运行当前进程的用户名qUser = Environment.UserName;/*检索此计算机上格式为"<驱动器号>:"的逻辑驱动器的名称,返回字符串数组,这是下一步操作的关键所在*/achDrives = Directory.GetLogicalDrives();//获取此字符串数组的维数,确定有多少个逻辑驱动器nNumOfDrives = achDrives.Length;}
系统信息不需要进行操作,我们简单的用asp:Label将他们显示出来就行了。逻辑驱动器的个数在不同的服务器上是不定的,所以用不定长数组保存逻辑驱动器的名称,而且逻辑驱动器的名称也是我们下一步浏览目录和文件的基础,故我们采用了数据网格DataGrid来显示和处理它。
显示和处理逻辑驱动器名称的DataGrid的代码(代码在listdrivers.aspx文件):
<asp:DataGrid id="DriversGrid" runat="server" AutoGenerateColumns="false"><Columns><asp:BoundColumn HeaderText="ID" DataField="ID" /><asp:BoundColumn HeaderText="磁盘名" DataField="Drivers" /><asp:HyperLinkColumnHeaderText="详细信息" DataNavigateUrlField="Drivers" DataNavigateUrlFormatString="listdir.aspx?dir={0}" DataTextField="Detail" Target="_new" /></Columns></asp:DataGrid>
前两个BoundColumn列都是显示序号和实际逻辑驱动器名称的,需要说明的是第三列,我们在进入各个逻辑驱动器显示目录和文件之前需要将所选择的逻辑驱动器的名称传递到显示目录的文件去,所以需要一个特殊的超级链接行HyperLinkColumn,我们将DataNavigateUrlField设置为数据源中要绑定到 HyperLinkColumn 中的超级链接的 URL 的字段,在此即逻辑驱动器名称。然后将DataNavigateUrlFormatString设置为当 URL 数据绑定到数据源中的字段时,此HyperLinkColumn中的超级链接的 URL 的显示格式,即要链接到的下一级处理页面,在此为listdir.aspx?dir={用户点击行的逻辑驱动器名称}
创建数据源的代码(代码在listdrivers.aspx.cs文件中):
//通过此方法返回一个集合形式的数据视图DataViewICollection CreateDataSource() {//定义内存中的数据表DataTableDataTable dt = new DataTable();//定义DataTable中的一行数据DataRowDataRow dr;/*向DataTable中增加一个列,格式:DataColumn("Column", type)Column为数据列的名字,type为数据列的数据类型*/dt.Columns.Add(new DataColumn("ID", typeof(Int32)));dt.Columns.Add(new DataColumn("drivers", typeof(string)));dt.Columns.Add(new DataColumn("detail", typeof(string)));//使用for循环将逻辑驱动器的名称以行的形式添加到数据表DataTable中for (int i = 0; i < nNumOfDrives; i++) {//定义新行dr = dt.NewRow();//对行中每列进行赋值,注意要与上边定义的DataTable的行相对应dr[0] = i; //循环生成的序号dr[1] = achDrives.ToString(); //逻辑驱动器的名称dr[2] = "查看详情";//向DataTable中添加行dt.Rows.Add(dr);}//根据得到的DataTable生成自定义视图DataViewDataView dv = new DataView(dt);//返回得到的视图DataViewreturn dv;}
我们通过这个方法得到了一个包含所有我们需要的数据的数据视图DataView,我们只需要在此aspx页的Page_Load方法中将此数据视图绑定到DataGrid上就可以了。
数据绑定代码(代码在listdrivers.aspx.cs文件中):
/* 设置DataGrid的数据源DataSource为我们从CreateDataSource()方法得到的数据视图DataView */DriversGrid.DataSource = CreateDataSource();//将此DataGrid进行数据绑定DriversGrid.DataBind();
通过上边介绍的几种主要方法我们就实现了获取系统信息和显示所有逻辑驱动器名称的功能,并且可以通过相应的链接进入下一个显示目录和文件名的程序listdir.aspx显示该逻辑驱动器下的所有目录和文件。
程序二:显示目录中所有子目录和文件的程序listdir.aspx
目录下有子目录和文件两种形式,必须分别对待。我们调用此程序本身对子目录进行列表显示,而文件我们需要调用showfile.aspx程序对文件的属性和内容进行显示。并且两者还有不同的删除方法,所以我们在这里设置了两个DataGrid,两个DataTable,两个DataView,分别处理和显示目录和文件。
显示和处理目录和文件的DataGrid的代码(代码在listdir.aspx文件):
显示目录或文件的序号和名称的数据列类似于listdrivers.aspx程序中的相应代码,这里就不再重复了。对于子目录和文件分别有各自的处理页面,所以需要导航到两个不同的页面,对于子目录,我们继续使用listdir.aspx程序对其下的子目录和文件进行列表显示:
<asp:HyperLinkColumn DataNavigateUrlField="DirName"DataNavigateUrlFormatString="listdir.aspx?dir={0}"DataTextField="DirDetail" HeaderText="详细信息"Target="_new"/>
对于文件,我们使用showfile.aspx程序显示其属性和内容:
<asp:HyperLinkColumn DataNavigateUrlField="FileName"DataNavigateUrlFormatString="showfile.aspx?file={0}" DataTextField="FileDetail" HeaderText="详细信息" Target="_new" />
在两个DataGrid(DirGrid,FileGrid)中我们分别设置了两个HyperLinkColumn列来导航到不同的处理页面。
在两个DataGrid中我们都使用了一个删除的按钮列:
<asp:ButtonColumn HeaderText="删除" Text="删除" CommandName="Delete"/>
由于添加、更新、删除功能列都是DataGrid的默认模板列,所以可以在Vs.net中通过DataGrid的属性生成器自动添加此列。
获取上一页面所传递来的参数的代码:
因为在下面产生数据源的方法中需要使用由上一个页面传递过来的参数来确定目录和文件的名称,所以在页面的Page_Load方法里使用了下列代码:
strDir2List = Request.QueryString["dir"];
字符串strDir2List即传过来的目录名或文件名。
因为我们使用了两个DateGrid,就需要进行两次数据绑定,就有两个不同的生成数据源的方法。
生成目录数据网格(DirGrid)数据源的方法:
//通过此方法返回一个集合形式的数据视图DataView,用来初始化子目录的DataGridICollection CreateDataSourceDir() {dtDir = new DataTable();DataRow dr;//向DataTable中添加新的数据列,共四列dtDir.Columns.Add(new DataColumn("DirID", typeof(Int32)));dtDir.Columns.Add(new DataColumn("DirName", typeof(string)));dtDir.Columns.Add(new DataColumn("DelDir", typeof(string)));dtDir.Columns.Add(new DataColumn("DirDetail", typeof(string))); //根据传入的参数(目录名)得到此目录下所有子目录名的字符串数组string [] DirEntries = Directory.GetDirectories(strDir2List);//使用foreach循环可以对未知长度的数组进行遍历循环foreach(string DirName in DirEntries){dr = dtDir.NewRow();dr[0] = i;//序号dr[1] = DirName;//文件夹名称 dr[3] = "删除";dr[3] = "查看详情";dtDir.Rows.Add(dr);i++; }DataView dvDir = new DataView(dtDir);//返回得到的数据视图return dvDir;}生成文件数据网格(FileGrid)数据源的方法://通过此方法返回一个集合形式的数据视图DataView,用来初始化文件的DataGridICollection CreateDataSourceFile() {dtFile = new DataTable();DataRow dr;dtFile.Columns.Add(new DataColumn("FileID", typeof(Int32)));dtFile.Columns.Add(new DataColumn("FileName", typeof(string)));dtFile.Columns.Add(new DataColumn("DelFile", typeof(string)));dtFile.Columns.Add(new DataColumn("FileDetail", typeof(string))); //根据传入的参数(目录名)得到此目录下所有文件名的字符串数组string [] FileEntries = Directory.GetFiles(strDir2List);foreach(string FileName in FileEntries){dr = dtFile.NewRow();dr[0] = i;dr[1] = FileName; dr[2] = "删除";dr[3] = "查看详情";dtFile.Rows.Add(dr);i++;}dvFile = new DataView(dtFile);return dvFile;}
我们编程实现了两个DataSource只需在页面的Page_Load方法里对两个DataGrid进行数据绑定即可将得到的DataTable中的数据显示在aspx页面的DataGrid上。
数据绑定代码:
//对子目录数据列表DirGrid进行数据源定义和数据绑定DirGrid.DataSource = CreateDataSourceDir();DirGrid.DataBind(); //对文件数据列表FileGrid进行数据源定义和数据绑定FileGrid.DataSource = CreateDataSourceFile();FileGrid.DataBind();
通过我们上边介绍的主要方法,我们实现了对某个逻辑驱动器或目录中的所有子目录和文件进行了列表显示,并且可以根据显示结果更进一步的浏览子目录或者查看文件的属性和内容提要。浏览子目录仍然是通过listdir.aspx这个程序,没有任何子目录级别要求,没有目录深度限制。
删除子目录和文件的主要方法和代码:
在删除子目录时,我们需要用到Directory.Delete (string,bool)方法,此方法有两种:
1.public static void Delete(string);
从指定路径删除空目录。
2.public static void Delete(string, boolean);
删除指定的目录并(如果指示)删除该目录中的任何子目录,将boolean设置为true的话,则删除此目录下的所有子目录和文件,否则将boolean设置为false。
在这里我们使用了第二种方法,如果选择删除的话,将删除此目录下的所有子目录和文件。
注意:Directory 类的所有方法都是静态的,因而无需具有目录Directory的实例就可被调用。
/*实现删除子目录的方法,此方法为VS.NET自动添加,注意DataGridCommandEventArgs e为DirGrid中 CommandName="Delete" 的ButtonColumn的事件,通过此事件,我们可以得到是那一行的ButtonColumn按钮列被点击,进而确定我们需要删除的子目录的名称*/private void DirGrid_DeleteCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e){/*定义一个单元格,e.Item为此事件所发生行的所有项目,e.Item.Cells[1]为整个行的第二个单元格的内容,在此DataGrid中为子目录的名称*/TableCell ItemCell = e.Item.Cells[1];//得到此子目录的名称的字符串string item = ItemCell.Text;//删除此子目录Directory.Delete(item,true);//删除后进行数据绑定以更新数据列表DirGrid.DataBind();}
在删除文件时,我们需要用到File.Delete(string path);
注意:File 类的所有方法都是静态的,因而无需具有目录的实例就可被调用。
private void FileGrid_DeleteCommand(object source,System.Web.UI.WebControls.DataGridCommandEventArgs e) {TableCell ItemCell = e.Item.Cells[1];//得到此文件名称的字符串string item = ItemCell.Text;//删除此文件File.Delete(item);//删除后进行数据绑定以更新数据列表DirGrid.DataBind();}
通过上边的主要方法我们在页面上实现了一个删除某一个子目录或者文件的功能,此功能在测试时需要慎重使用,一旦删除无法通过常规方法恢复。其他如目录或文件改名、修改内容等方法都可以在此程序基础上添加相应的功能,实现方法也很简单。各位爱好者可以通过添加相应功能,使之扩充为一个基于Web的服务器文件管理系统。我们也可以由此看到这个程序的危害性,一个没有对此安全隐患采取防范措施的服务器的文件系统就都暴露在了使用此程序的用户面前。
程序三:显示文件属性和内容的程序showfile.aspx
在显示属性和内容时需要用到的两个主要的类:
System.IO.FileInfo:提供创建、复制、删除、移动和打开文件的实例方法,并且帮助创建 FileStream 对象。
System.IO.StreamReader:实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。除非另外指定,StreamReader的默认编码为 UTF-8,而不是当前系统的 ANSI 代码页。UTF-8 可以正确处理 Unicode 字符并在操作系统的本地化版本上提供一致的结果。
Showfile.aspx页面主要代码:
<asp:Label id="FileDetail" runat="server"/>
我们只是将文件的属性信息和部分内容显示在此Label上。所以没有其他复杂的代码。
获取文件信息和内容的主要代码都在Page_Load方法中(代码在showfile.aspx.cs文件中):
//接收传入的参数,确定需要操作的文件名称strFile2Show = Request.QueryString["file"];//根据文件名实例化一个FileInfo对象FileInfo fi = new FileInfo(strFile2Show);FileDetail.Text = "文件名:";FileDetail.Text += strFile2Show+"<br>";FileDetail.Text += "文件大小";//获得文件的大小,然后变换单位为KBFileDetail.Text += (fi.Length/1024).ToString()+"K<br>";FileDetail.Text += "创建文件时间:";//获得文件的创建日期FileDetail.Text += fi.CreationTime.ToString();FileDetail.Text += "上次访问时间:";//获得文件的上次访问日期FileDetail.Text += fi.LastAccessTime.ToString()+"<br>";FileDetail.Text += "上次写入时间:";//获得文件的上次写入日期FileDetail.Text += fi.LastWriteTime.ToString()+"<br>";//实例化一个StreamReader对象,用于读取此FileInfo的内容StreamReader FileReader = fi.OpenText();//定义一个长度为1000的字符数组作为缓冲区char[] theBuffer = new char[1000];/*ReadBlock方法:从当前流中读取最大数量的字符并从索引开始将该数据写入缓冲区。参数:char[] buffer:方法返回时,包含指定的字符数组int index:buffer 中开始写入的位置int count:最多读取的字符数*/int nRead = FileReader.ReadBlock(theBuffer,0,1000);FileDetail.Text += new String(theBuffer,0,nRead);//关闭此 StreamReader 并释放与之关联的所有系统资源FileReader.Close();
到目前为止,我们实现了一个简单的web页面的服务器磁盘管理应用程序,可以查看、删除目录和文件。如果需要修改文件、新建文件和文件夹等功能,只需稍作修改,添加上相应的代码就可以。由于我们只是通过这个程序说明服务器中存在的安全隐患,所以在这里就不再实现这些功能了。
通过这三个简单的程序,我想大家已经能够清楚的认识到这一漏洞的危害性了,如果我们不加防范的话,其他用户的程序就能被恶意使用此功能的用户查看、删除,服务器的系统日志、系统文件也没有任何安全可言了。
解决方案
将FSO组件和删除或改名的方式我们不再过多的加以说明了,这一类的解决方法网络上已经有很多文章介绍了。
另外还有一种关于ASP的FSO组件漏洞的相应解决方案,即根据用户设置权限。在IIS里,可以设置每个站点的匿名访问所使用的帐号,默认为IUSR_ HostName,这一方法的原理就是针对每一个共享主机用户分别设置一个Windows帐号,如IUSR_HostName1,IUSR_ HostName 2等,然后将每一个用户限制在各自的Web目录下。
我们仔细的研究一下这种方案,可以发现这个方案无法真正实现安全。因为系统运行ASP时并不是使用的IUSR_ HostName帐号,而是IWAM_ HostName帐号,就象在ASP.NET中使用的用户ASPNET一样。也就是说每个ASP程序所拥有的权限并不是IUSR_ HostName的权限,而是IWAM_HostName用户的权限。这样的方法无法真正的将每个共享主机用户的文件系统访问权限限制在各自的虚拟站点中,每个用户仍然可以访问别人的代码。所以这种方法在ASP.NET中无法真正实现用户之间的安全性。
在ASP.NET中相应的运行ASP.NET程序的帐号为ASPNET,和上面所说的ASP中的解决方案类似,我们只能限制此用户不能访问系统目录等其他目录,但是无法防止用户访问其他共享主机用户的程序代码,无法从根本上杜绝这种问题。
那么,有没有真正的解决方案了呢?
有!这就是.NET Framework 的新特性――代码访问安全性
为了更好的理解这一问题的解决方法,我们需要先介绍一下.NET Framework的安全机制。然后再结合我们的实际问题来讨论解决方案。
为了解决安全问题,.NET Framework提供了一种称为代码访问安全性的安全机制。代码访问安全性允许根据代码的来源和代码的标识等属性将代码设置为不同级别的信任代码,同时还详细定义了不同级别的对代码的信任,从而可以详细的对代码设置各自的权限而不是将最大权限赋给所有的代码。使用代码访问安全性,可以减小恶意代码或各种错误的代码带来的严重的系统安全性问题的可能性。您可以设置允许代码执行的一组操作,同样可以设置永远不允许代码执行的一组操作。
实现代码访问安全性的基础就是JIT(运行时编译)和IL(中间代码)。所以所有以公共语言运行库为目标的托管代码都会受益于代码访问安全性。非托管代码则无法完全使用代码访问安全性。
下面我们将介绍一下代码访问安全性实现的各种功能:
代码访问安全性是控制代码对受保护资源和操作的访问权限的一种机制。在 .NET Framework中,代码访问安全性执行下列功能:
· 定义权限和权限集,它们表示访问各种系统资源的权限。
· 使管理员能够通过将权限集与代码组关联来配置安全策略。
· 使代码能够请求运行所需权限以及其他一些有用的权限,以及指定代码绝对不能拥有哪些权限。
· 根据代码请求的权限和安全策略允许的操作,向加载的每个程序集授予权限。
· 使代码能够要求其调用方拥有特定的权限。
· 使代码能够要求其调用方拥有数字签名,从而只允许特定组织或特定站点的调用方来调用受保护的代码。
· 通过将调用堆栈上每个调用方所授予的权限与调用方必须拥有的权限相比较,加强运行时对代码的限制。
为了确定是否已授予代码相应的权限,.NET运行库的安全系统将遍历整个调用堆栈,将每个调用方所授予的权限与目前要求的权限相比较。如果调用堆栈中的任何调用方没有要求的权限,则会引发安全性异常,并会拒绝访问和相应的操作。堆栈步旨在防止引诱攻击;在这种攻击中,受信程度较低的代码调用高度信任的代码,并使用高度信任的代码执行未经授权的操作。在运行时要求所有调用方都拥有权限将影响性能,但对防止代码遭受攻击至关重要。若要优化性能,可以使代码执行较少的堆栈步;但是,任何时候这样做时均必须确保不会暴露安全缺陷。
还存在另外一种代码访问安全性的常见用途,即应用程序将控件从网络 Web 站点直接下载到客户端,这种方式的代码安全性也是可以在客户端进行设置的,根据签名等数据权限证书来确定是不是可以允许下载的控件运行。这种方法类似于ActiveX的安全性设置,但是比之在设置权限更加详细和强大。同JAVA APPLET的沙箱安全机制相比,.NET 的客户端控件可以在本地简单设置后访问客户端的各种资源。由于这一方面的用途不是我们的重点,所以我们在这里就不再更详细的讨论其用途及其实现原理了。
下面我们就谈谈如何应用这一安全特性来解决ASP.NET中存在的系统安全漏洞。由于我们介绍的系统是共享主机,所以有其特殊性,即系统管理员无法事先给所有的代码赋予相应的权限,因为每个用户都可能有各种权限要求,并且这些要求特殊权力的代码在使用中都可能出现的,所以在权限管理上随时都有各种要求。
因此在权限设置方面,不仅仅是管理员设置,也包括了各个共享主机用户的权限请求,这也正是安全代码机制的一个重要部分。
请求权限是您让运行库知道代码执行有哪些操作权限的方法。通过将属性(声明式语法)放到代码的程序级范围来为程序集请求权限。
请求内置权限的代码示例:
//The attribute is placed on the assembly level.using System.Security.Permissions;[assembly:PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
将此段代码放在程序的开始部分(namespace声明之前),在编译时就会将请求的权限存储在程序集清单中。加载时,运行库检查权限请求,并应用安全策略规则来确定授予程序集哪些权限。
虽然我们编写的大部分代码都没有请求权限,其实不管是共享主机形式还是独立服务器形式都应该请求权限,这是因为请求权限有助于确保只将代码需要的权限授予代码。如果没有授予代码额外权限,即使某些恶意代码想利用您的代码来进行安全性破坏,它也无法操作没有赋给您自己代码相应权限的额外系统资源。您只应该请求代码需要的那些权限,而不应请求更多权限。
代码请求权限之后,系统管理员可以使用"权限查看"工具 (Permview.exe,位于您的.NET Framework的目录的bin目录下) 来检查您的程序集并根据其他条件来设置安全策略以决定是否给您的代码所请求的相应权限。如果您不显式地在代码中请求应用程序需要的权限,那么管理员将很难管理您的应用程序。在权限管理严格的主机上,将无法实现您的代码所要求的功能。
请求权限会通知运行库应用程序正常运行需要哪些权限,或具体不需要哪些权限。在.NET Framework安装后的默认状态下,所有代码都是FullTrust(完全信任)的。这时是不需要申请任何权限的,但是管理员一旦修改了代码安全,我们使用的磁盘访问就要受到限制了,这是就需要申请相应的权限了。我们上边介绍的文件管理代码就需要具有本地硬盘读写操作的能力,则应用程序必须拥有 FileIOPermission。如果代码不请求 FileIOPermission,在本地安全设置不允许应用程序拥有此权限的主机上,在应用程序尝试磁盘操作时就会引发安全性异常。即使应用程序能够处理此异常,也不会允许它操作磁盘。当然,如果您的代码不访问受保护的资源或执行受保护的操作,则不必请求任何权限。例如,如果代码只根据向它传递的输入来计算结果而不使用任何资源,则不必请求权限。如果您的代码访问受保护的资源但未请求必要的权限,则仍可能允许它执行,但如果它尝试访问某种资源而它又没有必要的权限,则可能在执行过程中失败。
系统管理员在得到了用户的权限申请后,可以根据情况考虑是否赋予用户相应的权限,在这里我们来看一下相应代码权限设置的具体方法。
在我们安装成功.NET Framework之后,在Windows 2000 Server的管理工具里多了两项管理工具: Microsoft .NET Framework Configration和Microsoft .NET Framework Wizards。这两种管理工具要实现的功能差不多,只不过Microsoft .NET Framework Wizards是通过向导方式设置,如果您对于.NET Framewrk的安全性操作不是很熟悉的话,可以使用向导根据系统提示一步步的来设置相关的权限。

Microsoft .NET Framework Wizards界面

Microsoft .NET Framework Wizards界面
使用Microsoft .NET Framework Wizards可以简单的设置.NET Framework的权限。但是我们为了更好的管理各个代码的权限,还是使用Microsoft .NET Framework Configuration来详细的设置我们所需的权限。

(Microsoft .NET Framework Configuration主界面)
在Microsoft .NET Framework Configuration中可以设置所有关于.NET Framework的属性。
点击我的电脑,打开下拉菜单,我们可以看到程序集缓存、已配置程序集、远程处理服务、运行库安全策略、应用程序等五项。运行库安全策略设置是我们这篇文章的重点。
我们可以先查看一下程序集缓存,在这里我们可以看到所有的全局程序集缓存,全局程序集缓存中存储了专门指定给由计算机中若干应用程序共享的程序集。在这里我们可以发现我们可以使用的所有的程序集,同时也可以添加和删除某些程序集。详细操作请参见.NET Framework SDK文档。
我们在这里主要讨论的是运行库安全策略。在此策略中,按层次结构由高到低分为四个级别,即:企业、计算机、用户、应用程序。在计算权限授予时,运行库从该层次结构的顶部开始,然后向下进行计算。较低的策略级别不能对在较高级别上授予的权限进行增加,但是可以使权限减少。这就是说如果我们将计算机策略设置为较小的权限时,可以不必更改企业策略就可以使设置的权限生效,也就是说权限检查的顺序是从低级别到高级别,只有在低级别中不存在的设置才会检查上一级的设置。默认情况下,用户策略和应用程序域策略的限制性小于计算机策略和企业级策略。大部分默认策略存在于计算机级别。所以我们需要将默认安装的主机的权限在计算机级别上进行修改,修改的内容根据主机是不是共享主机,主机应用的其他不明代码的可能性来设置。如果是我们讨论的共享主机的话,在计算机级别上就尽量将权限设的小一些,为了避免我们讨论的文件系统安全问题,一定要注意权限中的本地磁盘访问权限。
我们打开计算机策略设置可以发现几个默认的代码组、权限集和策略程序集。
根据需要,我们可以添加代码组和自定义的权限集。
在添加代码组的时候可以选择几种条件,主要的条件类型:默认为All Code、应用程序目录、哈希、强名称、作者、站点等。
对于我们所要讨论的共享主机,我们需要将My_Computer_Zone下的All Code的权限更改为不能进行磁盘读写,在更改之前,我们需要先定义一个权限集。这一权限集的作用就是将我们需要点击权限集,右键快捷菜单中选择新建,会出现一个创建权限集的窗口,这里需要给我们新建的权限集命名。下一步就是将单个权限分配给权限集。如下图所示。

在这里我们可以给这个新建的权限集赋予一个的系统权限,如上图所示,可用的权限包括:目录服务、DNS、事件日志、环境变量、文件IO、OLEDB数据库操作、注册表等等。我们主要要说明的是文件IO操作,其他的权限操作可以根据自己的需求来设置。这里我们就不再说明了。
在文件IO的权限设置中我们可以自定义针对每一个目录的权限,这里包括读、写、追加、路径盘等操作,在这里我们可以将我们需要的目录权限添加到列表中。因为我们是利用这一权限使所有没有配置权限的代码不可以进行文件IO操作,所以我们不强文件IO添加到分配的权限中。
新建了这一权限集后,我们更改一下默认设置,即将All Code的权限设置为此新建的权限集,也就是说所有没有在此定义代码都不能访问文件IO系统。
这里需要注意一件事情,因为Microsoft .NET Framework Configuration本身也需要文件IO权限,如果没有单独分配给Configuration一个文件IO操作权限的话,那么您就不能再次使用Configuration来设置权限了,只能重新安装.NET Framework了。所以我们需要将FullTrust权限分配给Configuration所使用的Dll,即mscorcfg.dll。在添加时,成员条件可以选择强名称,使用"导入",到winnt/window .net/framework/versionnumber/下选择mscorcfg.dll。如果需要运行其他配置程序,还需要设置相应的权限,这些系统程序一般都在系统程序集缓存中。
这样我们就完成了一个简单的设置,可以防止任何未经验证的代码访问文件IO系统。这样就从根本上防止了磁盘恶意操作。
如果您今后需要利用这一功能或者有共享主机用户需要使用文件IO功能,那么您可以在Microsoft .NET Framework Configuration中将其加入代码,如果不能使其使用其他功能,可以仅仅设置一个只具有文件IO权限的权限集。如果是共享主机用户您还可以给他分配直接到其所使用的目录的全部读写权限,对于他的日志文档,您可以将读功能分配给用户。通过上边新建权限集时我们可以发现:权限集可以规定到每一个目录的读写权限,所以可以将用户锁定于其可以使用的目录中。当然对于共享主机提供商来说,最好的方法就是自己实现这些功能,然后配置权限系统使用户使用共享主机提供商的程序来实现他们的正常操作,而避免了恶意文件操作。
需要注意的是如果分配给每一个单独的程序相应的权限时,我们最好使用强名称这一方式或者其他的可验证方式,强名称由程序集的标识--其简单文本名称、版本号和区域性信息(如果提供)--加上公钥和数字签名组成。这就需要我们使用Sn.exe 来设置密钥、签名和签名验证。强名称保证了程序是开发人员开发的并且没有被改动。
在进行上面的设置之后,管理员可以根据用户的各种需求来设置不同的代码集和权限集。
我们已经简单的介绍了一下ASP.NET中关于文件IO系统的漏洞的防治方法,这一方法有些繁琐,但是却可以从根本上杜绝一些漏洞,由于.NET的JIT(运行时编译)和IL(中间语言),.NET可以在程序编译时检查程序的安全性设置,所以能从根本上防止一些非法访问。.NET的代码安全性的内容很全面,我们讨论的只是很少的一部分,更多的功能需要大家共同来探索、学习。
Jun
1
篇首语:原来改mdb为asp就能防下载是鬼话。
引子:昨天和animator试验了一下,把data.mdb文件改名为data.asp文件后放在wwwroot目录里。然后 在IE中输入data.asp路径后,发现IE显示一片空白,右键->察看源文件,跳出记事本,将内容另存为.mdb文件 ,用ACCESS打开,发现需要密码,也就是说至少文件头被破坏。
然后用Flashget试验下载data.asp文件,并另存为data.mdb文件,发现用ACCESS打开完好无损!!!看 来,好一些编程人员在开发的时候都认为,改了mdb后缀为asp就能防下载的概念,是错的!后台数据库被下载对于一个asp+a ccess的网站来说无疑是一场惨绝人寰的灾难。今天找了各方的文章,归纳一下有以下9种办法防止数据库被下载(欢迎补充):& nbsp;
1.发挥你的想象力 修改数据库文件名
不用说,这是最最偷懒的方法,但是若攻击者通过第三方途径获得了数据库的路径),就玩完了。比如说攻击者本来只能拿到list权 ,结果意外看到了数据库路径,就可以冠冕堂皇地把数据库下载回去研究了。另外,数据文件通常大小都比较大,起再隐蔽的文件名都瞒 不了人。故保密性为最低。
2.数据库名后缀改为ASA、ASP等
此法须配合一些要进行一些设置,否则就会出现本文开头的那种情况
(1)二进制字段添加(此招我还没有炼成-_-+)。
(2)在这个文件中加入<%或%>,IIS就会按ASP语法来解析,然后就会报告500错误,自然不能下载了。可是 如果只是简单的在数据库的文本或者备注字段加入<%是没用的,因为ACCESS会对其中的内容进行处理,在数据库里他会以 < %的形式存在,无效!正确的方法是将<%存入OLE对象字段里,这样我们的目的就能达到了。&nbs p;
作方法:
首先,用notepad新建一个内容为 <% 的 文本文件,随便起个名字存档。
接着,用Access打开您的数据库文件,新建一个表,随便起个名字,在表中添加一个OLE对象的字段,然后添加一个记录, 插入之前建立的文本文件,如果操作正确的话,应该可以看到一个新的名为"数据包"的记录。即可
3.数据库名前加"#"
只需要把数据库文件前名加上#、然后修改数据库连接文件(如conn.asp)中的数据库地址。原理是下载的时候只能识别& nbsp;#号前名的部分,对于后面的自动去掉,比如你要下载:http://www.pcdigest.com/date/# 123.mdb(假设存在的话)。无论是IE还是FLASHGET等下到的都是http://www.test.com/dat e/index.htm(index.asp、default.jsp等你在IIS设置的首页文档)
另外在数据库文件名中保留一些空格也起到类似作用,由于HTTP协议对地址解析的特殊性,空格会被编码为"%",如http ://www.test.com/date/123 ;456.mdb,下载的时http://www. test.com/date/123 %456.mdb。而我们的目录就根本没有123%456.mdb这个文件,所 以下载也是无效的这样的修改后,即使你暴露了数据库地址,一般情况下别人也是无法下载!
4.加密数据库
首先在选取"工具->安全->加密/解密数据库,选取数据库(如:employer.mdb),然后接确定,接 着会出现"数据库加密后另存为"的窗口,存为:employer1.mdb。接着employer.mdb就会被编码,然后存为 employer1.mdb..要注意的是,以上的动作并不是对数据库设置密码,而只是对数据库文件加以编码,目的是为了防止他 人使用别的工具来查看数据库文件的内容。
接下来我们为数据库加密,首先以打开经过编码了的 e mployer1.mdb,在打开时,选择"独占"方式。然后选取功能表的"工具->安全->设置数据库密码",& nbsp;接着输入密码即可。这样即使他人得到了employer1.mdb文件,没有密码他是无法看到 emplo yer1.mdb的。
加密后要修改数据库连接页, 如:
conn.open "driver={microsoft access driver&nb sp;(*.mdb)};uid=admin;pwd=数据库密码;dbq=数据库路径"
这样修改后,数据库即使被人下载了,别人也无法打开(前提是你的数据库连接页中的密码没有被泄露)
但值得注意的是,由于Access数据库的加密机制比较简单,即使设置了密码,解密也很容易。该数据库系统通过将用户输入的 密码与某一固定密钥进行"异或"来形成一个加密串,并将其存储在*.mdb文件从地址"&H42"开始的区域内。所以一 个好的程序员可以轻松制作一个几十行的小程序就可以轻松地获得任何Access数据库的密码。因此,只要数据库被下载,其信息安 全依然是个未知数。
5.数据库放在WEB目录外或将数据库连接文件放到其他虚拟目录下
如你的WEB目录是e:\webroot,可以把数据库放到e:\data这个文件夹里,在e:\webroot里的数据库 连接页中修改数据库连接地址为:"../data/数据库名" 的形式,这样数据库可以正常调用,但是无法下载的,因 为它不在WEB目录里!这个方法一般也不适合购买虚拟空间的用户。
6.使用ODBC数据源。
在ASP等程序设计中,如果有条件,应尽量使用ODBC数据源,不要把数据库名写在程序中,否则,数据库名将随ASP源代码 的失密而一同失密,例如: DBPath = Server.MapPath("../123/ abc/asfadf.mdb ")
conn.open "driver={Microsoft Access Driver&nb sp;(*.mdb)};dbq="& DBPath
可见,即使数据库名字起得再怪异,隐藏的目录再深,ASP源代码失密后,也很容易被下载下来。如果使用ODBC数据源,就不 会存在这样的问题了: conn.open "ODBC-DSN名" ,不过这样是比较烦的,目 录移动的话又要重新设置数据源了,更方便的方法请看第7,8法!
7.添加数据库名的如MDB的扩展映射
这个方法就是通过修改IIS设置来实现,适合有IIS控制权的朋友,不适合购买虚拟主机用户(除非管理员已经设置了)。这个 方法我认为是目前最好的。只要修改一处,整个站点的数据库都可以防止被下载。无须修改代码即使暴露目标地址也可以防止下载。&n bsp;
我们在IIS属性---主目录---配置---映射---应用程序扩展那里添加.mdb文件的应用解析。注意这里的选择的D LL(或EXE等)似乎也不是任意的,选择不当,这个MDB文件还是可以被下载的, 注意最好不要选择选 择asp.dll等。你可以自己多测试下
这样修改后下载数据库如:http://www.test.com/data/dvbbs6.mdb。就出现(404或50 0等错误)
8:使用.net的优越性
动网的木鸟就写过一个防非法下载文件的"WBAL 防盗链工具"。具体可以登陆http://www.9seek .com/WBAL/ ;
不过 那个只实现了防止非本地下载的 ,没有起到真正的防下载数据库的功能。不过这个方法已经跟5法差 不多可以通过修改.NET文件,实现本地也不能下载!
这几个方法中,只有第7和8个是统一性改的,一次修改配置后,整个站点的数据库都可以防止下载,其他几个就要分别修改数据库 名和连接文件,比较麻烦,不过对于虚拟主机的朋友也只能这样了!
其实第6个方法应该是第5个方法的扩展,可以实现特殊的功能,但对于不支持.net的主机或者怕设置麻烦的话,还是直接用第 5个方法了,而且默认情况下第6个方法,依然可以通过复制连接到同主机的论坛或留言本发表,然后就可以点击下载了(因为这样的引 用页是来自同主机的)
9.利用NTFS分区的文件权限设置(by percyboy)
我们已经知道,ASP.NET 中使用 ADO.NET 访问数据库,通过 OleDb 的连接可以访问 Access 数据库— —我们非常常用的低端数据库之一。本文讨论了 ASP.NET 中可能看到的若干错误提示,从中看到&nb sp;Access 2000 和 Access XP 创建的数据库文件 ,在访问出现错误时会出现不太相同的错误提示。希望对大家有所帮助。另一个要点是,希望通过此文,使大家对 ASP. NET 中 Access 数据库文件的 NTFS 权限设置有所新的认识 。
(一)实验过程
为了叙述方便,举个具体例子做个实验:应用程序为 /test ,数据库存放在 D:\wwwr oot\test\data\db1.mdb,我们已经知道在 ASP.NET 中是以一个叫做 ;ASPNET 虚拟用户的身份访问数据库的,我们需要给这个账户以特定的 NTFS 权限才能 使 ASP.NET 程序正常运行。
为了得到最严格的 NTFS 权限设置,实验开始时我们给程序最低的 NTFS 权限 :
a) D:\wwwroot\test\data\ 文件夹的给用户ASPNET 以如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;□ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
1.1 对于某个只包含有"Select"命令的aspx程序,上述权限设置运行时无障碍,即:上述权限 已经满足这类程序的运行了。
1.2 对于包含有"Update""Insert""Update"等命令的aspx程序, ;
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,出现如下错误:
"/test"应用程序中的服务器错误。
---------------------------------------
Microsoft Jet 数据库引擎打不开文件'D:\wwwroot\test\data\'。&n bsp;它已经被别的用户以独占方式打开,或没有查看数据的权限。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: Microsof t Jet 数据库引擎打不开文件'D:\wwwroot\test\data\'。 它已经被 别的用户以独占方式打开,或没有查看数据的权限。
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,出现如下错误:
"/test"应用程序中的服务器错误。
----------------------------------------------
操作必须使用一个可更新的查询。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: 操作必须使用一个 可更新的查询。
(c) 原因初步分析:因为包含有"Update""Insert""Update"等命令,需要对数据库文件本身进 行写入操作,所以上述权限不能满足此需求,我们需要进一步放开权限。
我们放开一些权限,
a) D:\wwwroot\test\data\ 文件夹不变: & nbsp;
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
1.3 放开权限后继续实验,
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,出现如下错误:
"/test"应用程序中的服务器错误。
------------------------------------------
不能锁定文件。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: 不能锁定文件。& nbsp;
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,没有出现错误。
(c) 原因初步分析:我们发现在打开 Access 数据库时,同时会在所在目录生成一个同名 的 *.ldb 文件,这是一个 Access 的锁定标记。鉴于此,我们猜测,用户 ASPNET 访问 Access 数据库时,也需要生成一个锁定标记,而该目录没 有允许其写入,因此出错。至于 Access XP 创建的数据库为什么没有这个错误,原因还不 得而知。
我们进一步放开权限,
a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以 如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
1.4 继续实验,发现错误已解决,那么上面这个权限就是我们需要放开的"最低权限"。
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,我们会发现一个小问题:生成的 *.ldb 文件不会自己删除,访问后该文件依然存在,但这个 问题不会影响 ASP.NET 的正常运行。
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,没有出现上面类似问题。
(c) 原因初步分析:我们仅仅是给了 ASPNET 以写入文件夹的权限,没有给它修改的权限 ,所以文件一旦写入,便无法修改其内容,*.ldb 也就删除不掉了。
如果非要解决这个问题,进一步放开权限为:
a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以 如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;√ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
1.5 附带着,实验另一种情形:我们把 db1.mdb 在 Acce ss 打开编辑,同时访问 ASP.NET。
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,我们发现并没有出现什么问题。
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,出现如下错误:
"/zhao"应用程序中的服务器错误。
------------------------------------------------
不能使用 '';文件已在使用中。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: 不能使用&nbs p;'';文件已在使用中。
(c) 原因初步分析:Access 数据库是单用户单线程的数据库,我们在 Access&n bsp;里面打开编辑数据库文件时其实是以当前 Windows 用户(比如Administrator) 身份打开数据库,而 ASP.NET 默认使用的是 ASPNET 虚拟用户(隶属于 Users 组),级别低于 Administrator,无法和 Adminis trator "抢夺"权限,所以出现冲突错误。至于 Access 2000 忽略 这个问题的情形我们也不必做讨论了,可能是 Access 2000 没有考虑那么多因素吧。& nbsp;
1.6 再附带一种情形:将 db1.mdb 的属性改为"只读",无论是&nbs p;Access 2000 还是 Access XP 都将分别出现与& nbsp;1.2 中各自的错误相同的错误提示。
(二)实验结论
(1) 我们首先再次总结一下 Access 数据库文件的 NTFS 权 限设置的缘起:
在 ASP.NET 中默认是以一个叫做 ASPNET& nbsp;的虚拟用户的身份来访问、操作数据库的,你可以在"控制面板"-"管理工具"-"计算机管理"-"本地用户和组"-" 用户"中看到这个用户,默认情况下是:
全名:ASP.NET 计算机帐户&nb sp;
描述为:用于运行 ASP.NET&nb sp;辅助进程(aspnet_wp.exe)的帐户。
隶属于:Users组。
使用这么一个隶属于 Users 组的用户来进行文件操作、数据库操 作的风险是要比用一个 Administrators 组的用户的风险要小得多,这也是 ASP .NET 在安全方面的一个考虑吧。
既然是这么一个用户需要访问、操作数据库文件本身,那么我们就需要给它一定的 NTFS 权限以允许它的访问。显然没有 NTFS 的权限许可,ASPNET 就无 法访问、操作数据库,就会出现上面实验中所看到的那些错误了。
(2) 经过上面的实验,我们已经知道如下的 NTFS 权限设置是可以满足一般需求的:&nb sp;
a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以 如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
同时我们也注意到 db1.mdb 是否为"只读"文件对 ASPNET 的访问也会 有一定影响。
(3) 上述权限设置可以直接设置给 ASPNET 用户自己,也可以设置给 Use rs 组,或者直接给 Everyone 组上述权限都是可以的。因为 ASPNET 隶属于 Users 组,可以通过 用户组 给 ASPNET 设置权限。
(4) NTFS 权限在文件或文件夹右击后得到的"属性"对话框-"安全"选项卡中设置,一般情况下,可 以考虑给 Adminitrators 组以"完全控制"的权限,同时不要轻易在"拒绝"中打勾,有关&n bsp;NTFS 权限设置的技巧,可以咨询网络管理员、网络安全专家的建议。
注:FAT, FAT32 格式的分区中不支持 NTFS 权限。 &nb sp;
(5) Windows 2000 系列,Windows Server 2003 系列的"安全"选项卡默认是很容易找到的,但 Windows XP Pr ofessional 中的"安全"选项卡默认是关闭的,可以将"控制面板"-"文件夹选项"-"查看"选项卡中的" 高级设置"中"使用简单共享(推荐)"一项的"√"去除,"确定"之后,再次按照上面的方法即可看到"安全"选项卡了。&nbs p;
===========
综上所述,2、3、4法一起使用,是防止数据库被下载最基本,最行之有效的方 法,既适用于对服务器有管辖权的网管,又适用于虚拟主机的用户,推荐每一个制作者同时必用这三种方法
若你对服务器拥有管辖权,推荐再加上方法9,你的ACCESS数据库的安全性 就可以大大提高了。
引子:昨天和animator试验了一下,把data.mdb文件改名为data.asp文件后放在wwwroot目录里。然后 在IE中输入data.asp路径后,发现IE显示一片空白,右键->察看源文件,跳出记事本,将内容另存为.mdb文件 ,用ACCESS打开,发现需要密码,也就是说至少文件头被破坏。
然后用Flashget试验下载data.asp文件,并另存为data.mdb文件,发现用ACCESS打开完好无损!!!看 来,好一些编程人员在开发的时候都认为,改了mdb后缀为asp就能防下载的概念,是错的!后台数据库被下载对于一个asp+a ccess的网站来说无疑是一场惨绝人寰的灾难。今天找了各方的文章,归纳一下有以下9种办法防止数据库被下载(欢迎补充):& nbsp;
1.发挥你的想象力 修改数据库文件名
不用说,这是最最偷懒的方法,但是若攻击者通过第三方途径获得了数据库的路径),就玩完了。比如说攻击者本来只能拿到list权 ,结果意外看到了数据库路径,就可以冠冕堂皇地把数据库下载回去研究了。另外,数据文件通常大小都比较大,起再隐蔽的文件名都瞒 不了人。故保密性为最低。
2.数据库名后缀改为ASA、ASP等
此法须配合一些要进行一些设置,否则就会出现本文开头的那种情况
(1)二进制字段添加(此招我还没有炼成-_-+)。
(2)在这个文件中加入<%或%>,IIS就会按ASP语法来解析,然后就会报告500错误,自然不能下载了。可是 如果只是简单的在数据库的文本或者备注字段加入<%是没用的,因为ACCESS会对其中的内容进行处理,在数据库里他会以 < %的形式存在,无效!正确的方法是将<%存入OLE对象字段里,这样我们的目的就能达到了。&nbs p;
作方法:
首先,用notepad新建一个内容为 <% 的 文本文件,随便起个名字存档。
接着,用Access打开您的数据库文件,新建一个表,随便起个名字,在表中添加一个OLE对象的字段,然后添加一个记录, 插入之前建立的文本文件,如果操作正确的话,应该可以看到一个新的名为"数据包"的记录。即可
3.数据库名前加"#"
只需要把数据库文件前名加上#、然后修改数据库连接文件(如conn.asp)中的数据库地址。原理是下载的时候只能识别& nbsp;#号前名的部分,对于后面的自动去掉,比如你要下载:http://www.pcdigest.com/date/# 123.mdb(假设存在的话)。无论是IE还是FLASHGET等下到的都是http://www.test.com/dat e/index.htm(index.asp、default.jsp等你在IIS设置的首页文档)
另外在数据库文件名中保留一些空格也起到类似作用,由于HTTP协议对地址解析的特殊性,空格会被编码为"%",如http ://www.test.com/date/123 ;456.mdb,下载的时http://www. test.com/date/123 %456.mdb。而我们的目录就根本没有123%456.mdb这个文件,所 以下载也是无效的这样的修改后,即使你暴露了数据库地址,一般情况下别人也是无法下载!
4.加密数据库
首先在选取"工具->安全->加密/解密数据库,选取数据库(如:employer.mdb),然后接确定,接 着会出现"数据库加密后另存为"的窗口,存为:employer1.mdb。接着employer.mdb就会被编码,然后存为 employer1.mdb..要注意的是,以上的动作并不是对数据库设置密码,而只是对数据库文件加以编码,目的是为了防止他 人使用别的工具来查看数据库文件的内容。
接下来我们为数据库加密,首先以打开经过编码了的 e mployer1.mdb,在打开时,选择"独占"方式。然后选取功能表的"工具->安全->设置数据库密码",& nbsp;接着输入密码即可。这样即使他人得到了employer1.mdb文件,没有密码他是无法看到 emplo yer1.mdb的。
加密后要修改数据库连接页, 如:
conn.open "driver={microsoft access driver&nb sp;(*.mdb)};uid=admin;pwd=数据库密码;dbq=数据库路径"
这样修改后,数据库即使被人下载了,别人也无法打开(前提是你的数据库连接页中的密码没有被泄露)
但值得注意的是,由于Access数据库的加密机制比较简单,即使设置了密码,解密也很容易。该数据库系统通过将用户输入的 密码与某一固定密钥进行"异或"来形成一个加密串,并将其存储在*.mdb文件从地址"&H42"开始的区域内。所以一 个好的程序员可以轻松制作一个几十行的小程序就可以轻松地获得任何Access数据库的密码。因此,只要数据库被下载,其信息安 全依然是个未知数。
5.数据库放在WEB目录外或将数据库连接文件放到其他虚拟目录下
如你的WEB目录是e:\webroot,可以把数据库放到e:\data这个文件夹里,在e:\webroot里的数据库 连接页中修改数据库连接地址为:"../data/数据库名" 的形式,这样数据库可以正常调用,但是无法下载的,因 为它不在WEB目录里!这个方法一般也不适合购买虚拟空间的用户。
6.使用ODBC数据源。
在ASP等程序设计中,如果有条件,应尽量使用ODBC数据源,不要把数据库名写在程序中,否则,数据库名将随ASP源代码 的失密而一同失密,例如: DBPath = Server.MapPath("../123/ abc/asfadf.mdb ")
conn.open "driver={Microsoft Access Driver&nb sp;(*.mdb)};dbq="& DBPath
可见,即使数据库名字起得再怪异,隐藏的目录再深,ASP源代码失密后,也很容易被下载下来。如果使用ODBC数据源,就不 会存在这样的问题了: conn.open "ODBC-DSN名" ,不过这样是比较烦的,目 录移动的话又要重新设置数据源了,更方便的方法请看第7,8法!
7.添加数据库名的如MDB的扩展映射
这个方法就是通过修改IIS设置来实现,适合有IIS控制权的朋友,不适合购买虚拟主机用户(除非管理员已经设置了)。这个 方法我认为是目前最好的。只要修改一处,整个站点的数据库都可以防止被下载。无须修改代码即使暴露目标地址也可以防止下载。&n bsp;
我们在IIS属性---主目录---配置---映射---应用程序扩展那里添加.mdb文件的应用解析。注意这里的选择的D LL(或EXE等)似乎也不是任意的,选择不当,这个MDB文件还是可以被下载的, 注意最好不要选择选 择asp.dll等。你可以自己多测试下
这样修改后下载数据库如:http://www.test.com/data/dvbbs6.mdb。就出现(404或50 0等错误)
8:使用.net的优越性
动网的木鸟就写过一个防非法下载文件的"WBAL 防盗链工具"。具体可以登陆http://www.9seek .com/WBAL/ ;
不过 那个只实现了防止非本地下载的 ,没有起到真正的防下载数据库的功能。不过这个方法已经跟5法差 不多可以通过修改.NET文件,实现本地也不能下载!
这几个方法中,只有第7和8个是统一性改的,一次修改配置后,整个站点的数据库都可以防止下载,其他几个就要分别修改数据库 名和连接文件,比较麻烦,不过对于虚拟主机的朋友也只能这样了!
其实第6个方法应该是第5个方法的扩展,可以实现特殊的功能,但对于不支持.net的主机或者怕设置麻烦的话,还是直接用第 5个方法了,而且默认情况下第6个方法,依然可以通过复制连接到同主机的论坛或留言本发表,然后就可以点击下载了(因为这样的引 用页是来自同主机的)
9.利用NTFS分区的文件权限设置(by percyboy)
我们已经知道,ASP.NET 中使用 ADO.NET 访问数据库,通过 OleDb 的连接可以访问 Access 数据库— —我们非常常用的低端数据库之一。本文讨论了 ASP.NET 中可能看到的若干错误提示,从中看到&nb sp;Access 2000 和 Access XP 创建的数据库文件 ,在访问出现错误时会出现不太相同的错误提示。希望对大家有所帮助。另一个要点是,希望通过此文,使大家对 ASP. NET 中 Access 数据库文件的 NTFS 权限设置有所新的认识 。
(一)实验过程
为了叙述方便,举个具体例子做个实验:应用程序为 /test ,数据库存放在 D:\wwwr oot\test\data\db1.mdb,我们已经知道在 ASP.NET 中是以一个叫做 ;ASPNET 虚拟用户的身份访问数据库的,我们需要给这个账户以特定的 NTFS 权限才能 使 ASP.NET 程序正常运行。
为了得到最严格的 NTFS 权限设置,实验开始时我们给程序最低的 NTFS 权限 :
a) D:\wwwroot\test\data\ 文件夹的给用户ASPNET 以如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;□ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
1.1 对于某个只包含有"Select"命令的aspx程序,上述权限设置运行时无障碍,即:上述权限 已经满足这类程序的运行了。
1.2 对于包含有"Update""Insert""Update"等命令的aspx程序, ;
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,出现如下错误:
"/test"应用程序中的服务器错误。
---------------------------------------
Microsoft Jet 数据库引擎打不开文件'D:\wwwroot\test\data\'。&n bsp;它已经被别的用户以独占方式打开,或没有查看数据的权限。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: Microsof t Jet 数据库引擎打不开文件'D:\wwwroot\test\data\'。 它已经被 别的用户以独占方式打开,或没有查看数据的权限。
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,出现如下错误:
"/test"应用程序中的服务器错误。
----------------------------------------------
操作必须使用一个可更新的查询。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: 操作必须使用一个 可更新的查询。
(c) 原因初步分析:因为包含有"Update""Insert""Update"等命令,需要对数据库文件本身进 行写入操作,所以上述权限不能满足此需求,我们需要进一步放开权限。
我们放开一些权限,
a) D:\wwwroot\test\data\ 文件夹不变: & nbsp;
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
1.3 放开权限后继续实验,
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,出现如下错误:
"/test"应用程序中的服务器错误。
------------------------------------------
不能锁定文件。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: 不能锁定文件。& nbsp;
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,没有出现错误。
(c) 原因初步分析:我们发现在打开 Access 数据库时,同时会在所在目录生成一个同名 的 *.ldb 文件,这是一个 Access 的锁定标记。鉴于此,我们猜测,用户 ASPNET 访问 Access 数据库时,也需要生成一个锁定标记,而该目录没 有允许其写入,因此出错。至于 Access XP 创建的数据库为什么没有这个错误,原因还不 得而知。
我们进一步放开权限,
a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以 如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
1.4 继续实验,发现错误已解决,那么上面这个权限就是我们需要放开的"最低权限"。
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,我们会发现一个小问题:生成的 *.ldb 文件不会自己删除,访问后该文件依然存在,但这个 问题不会影响 ASP.NET 的正常运行。
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,没有出现上面类似问题。
(c) 原因初步分析:我们仅仅是给了 ASPNET 以写入文件夹的权限,没有给它修改的权限 ,所以文件一旦写入,便无法修改其内容,*.ldb 也就删除不掉了。
如果非要解决这个问题,进一步放开权限为:
a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以 如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;√ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
1.5 附带着,实验另一种情形:我们把 db1.mdb 在 Acce ss 打开编辑,同时访问 ASP.NET。
(a) 如果 db1.mdb 是 Access 2000 创 建的数据库,我们发现并没有出现什么问题。
(b) 如果 db1.mdb 是 Access XP 创建的 数据库,出现如下错误:
"/zhao"应用程序中的服务器错误。
------------------------------------------------
不能使用 '';文件已在使用中。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误 以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.OleDb.OleDbException: 不能使用&nbs p;'';文件已在使用中。
(c) 原因初步分析:Access 数据库是单用户单线程的数据库,我们在 Access&n bsp;里面打开编辑数据库文件时其实是以当前 Windows 用户(比如Administrator) 身份打开数据库,而 ASP.NET 默认使用的是 ASPNET 虚拟用户(隶属于 Users 组),级别低于 Administrator,无法和 Adminis trator "抢夺"权限,所以出现冲突错误。至于 Access 2000 忽略 这个问题的情形我们也不必做讨论了,可能是 Access 2000 没有考虑那么多因素吧。& nbsp;
1.6 再附带一种情形:将 db1.mdb 的属性改为"只读",无论是&nbs p;Access 2000 还是 Access XP 都将分别出现与& nbsp;1.2 中各自的错误相同的错误提示。
(二)实验结论
(1) 我们首先再次总结一下 Access 数据库文件的 NTFS 权 限设置的缘起:
在 ASP.NET 中默认是以一个叫做 ASPNET& nbsp;的虚拟用户的身份来访问、操作数据库的,你可以在"控制面板"-"管理工具"-"计算机管理"-"本地用户和组"-" 用户"中看到这个用户,默认情况下是:
全名:ASP.NET 计算机帐户&nb sp;
描述为:用于运行 ASP.NET&nb sp;辅助进程(aspnet_wp.exe)的帐户。
隶属于:Users组。
使用这么一个隶属于 Users 组的用户来进行文件操作、数据库操 作的风险是要比用一个 Administrators 组的用户的风险要小得多,这也是 ASP .NET 在安全方面的一个考虑吧。
既然是这么一个用户需要访问、操作数据库文件本身,那么我们就需要给它一定的 NTFS 权限以允许它的访问。显然没有 NTFS 的权限许可,ASPNET 就无 法访问、操作数据库,就会出现上面实验中所看到的那些错误了。
(2) 经过上面的实验,我们已经知道如下的 NTFS 权限设置是可以满足一般需求的:&nb sp;
a) D:\wwwroot\test\data\ 文件夹给用户ASPNET以 如下权限:
允许 拒绝
完全控制 &n bsp; □ & nbsp;□
修改 &nbs p; &nbs p;□ □
读取及运行 & nbsp; √ □ ;
列出文件夹目录 ; √ □
读取 &nbs p; &nbs p;√ □
写入 &nbs p; &nbs p;√ □
b) D:\wwwroot\test\data\db1.mdb 文件本身给用户ASPNET以如下权限:
√ 允许将来自父系的可继承权限传播给该 对象
同时我们也注意到 db1.mdb 是否为"只读"文件对 ASPNET 的访问也会 有一定影响。
(3) 上述权限设置可以直接设置给 ASPNET 用户自己,也可以设置给 Use rs 组,或者直接给 Everyone 组上述权限都是可以的。因为 ASPNET 隶属于 Users 组,可以通过 用户组 给 ASPNET 设置权限。
(4) NTFS 权限在文件或文件夹右击后得到的"属性"对话框-"安全"选项卡中设置,一般情况下,可 以考虑给 Adminitrators 组以"完全控制"的权限,同时不要轻易在"拒绝"中打勾,有关&n bsp;NTFS 权限设置的技巧,可以咨询网络管理员、网络安全专家的建议。
注:FAT, FAT32 格式的分区中不支持 NTFS 权限。 &nb sp;
(5) Windows 2000 系列,Windows Server 2003 系列的"安全"选项卡默认是很容易找到的,但 Windows XP Pr ofessional 中的"安全"选项卡默认是关闭的,可以将"控制面板"-"文件夹选项"-"查看"选项卡中的" 高级设置"中"使用简单共享(推荐)"一项的"√"去除,"确定"之后,再次按照上面的方法即可看到"安全"选项卡了。&nbs p;
===========
综上所述,2、3、4法一起使用,是防止数据库被下载最基本,最行之有效的方 法,既适用于对服务器有管辖权的网管,又适用于虚拟主机的用户,推荐每一个制作者同时必用这三种方法
若你对服务器拥有管辖权,推荐再加上方法9,你的ACCESS数据库的安全性 就可以大大提高了。