??xml version="1.0" encoding="utf-8" standalone="yes"?>
[JS]Cookie_N之?
www.fh888.com 2006-9-17 16:25:00
发布QCary
媒体Qwww.JustDN.org 作者:Jim Park
转自Q?font style="background-color: #dee0fe">http://www.fh888.com/showfile.html?projectid=5&username=cary&articleid=8C17CE3AA29B4479805CB416B9ADF89F
<!—CookiesQ有些h喜欢它们Q有些h憎恨它们。但是,很少有h真正知道如何使用它们。现在你可以成ؓ数Z的成员-可以自傲的Cookie 大师?->
如果你象作者一栯性不好,那么你可能根本记不住Z的名字。我遇到人时Q多半只是点点头Q问?#8220;吃了嘛!”Q而且期望问候到此ؓ止。如果还需要表CZ什么,那么我就得求助于一些狡猄技巧,好让我能惛_Ҏ谁。比如胡扯v一些和Ҏ有关的hQ不他们之间关pdq,只要能避免不记得Ҏ名字的尴就好: “你隔壁邻居的侄子的可爱小狗迈菲斯Ҏ么P”通过q个ҎQ我希望能让Ҏ感到Q我实很重视他Q她Q,甚至q记得这些琐事,虽然实际上连名字都忘C。但是,不是我不重视Q而是我的记忆力实在是p糕Q而且要记住的名字又实在太多。如果我能给每个|cookiesQ那么我׃会再犯这U记忆力问题了?br />
在这文章里Q我们要学习Q?br />
1. 什么是 Cookies?
2. Cookie 的构?br />
3. 操纵 Cookies
4. Cookie 怪兽
什么是Cookies?
你会问,什么是cookies? cookie 是浏览器保存在用戯机上的量数据。它与特定的WEB|WEB站点兌hQ自动地在WEB览器和WEB服务器之间传递?br />
比如Q如果你q行的是Windows操作pȝQ用Internet Explorer上网Q那么你会发现在你的“Windows”目录下面有一个子目录Q叫?#8220;Temporary Internet Files”。如果你有空看看q个目录Q就会发现里面有一些文Ӟ文g名称看v来就象电子邮件地址。比如在我机器上的这个目录里Q就?“jim@support.microsoft.com”q样的文件。这是一个cookie 文gQ这个文件从哪来呢?猜一猜,它来自微软的支持站点。顺便说一句,q不是我的电子邮件地址Q特此澄清?br />
对于理l小的、不重要的、不想保存在中央数据库里的细节信息,Cookies 是个很不错的Ҏ。(q不是说大家的名字不重要。)比如Q目前网站上不断增长的自定义服务Q可以ؓ每个用户定制他们要看的内宏V如果你设计的就是这样一个站点,那么你怎么来管理这L信息Q一个用户喜Ƣ绿色的菜单条,而另一个喜Ƣ红色的。确实是个篏人的问题。不q,q样的信息,可以很安全地记录到cookieQƈ保存在用L计算ZQ而你自己的数据库I间可以留给更长久更有意义的数据?br />
FYI: Cookies 对于安全用途,通常很有用。我不想在此p一问题q于深入Q只是提供一个示例,可以看到如何使用在一D|间之后过期的cookies来保证站点安全:
1. 使用用户名和口oQ通过 SSL d?br />
2. 在服务器的数据库里检查用户名和口令。如果登录成功,建立一个当前时间标{消息摘要 (比如 MD5) Qƈ把它保存在cookie和服务器数据库里。把用户的登录时间保存在服务器数据库里面的用戯录里?br />
3. 在进行每个安全事务时Q用户处于登录状态的M事务Q,把cookie的消息摘要和保存在服务器数据库里的摘要进行比较,如果比较p|Q就把用户引导到d界面?br />
4. 如果W?步检查通过Q那么检查当前时间和d旉之音l过的时间是否超q允许的旉长度。如果用户已l超Ӟ那么把用户引到d界面?br />
5. 如果W?步和W?步都通过了,那么把登录时间重新设|成当前旉Q允怺务发生。那些需要你d的安全站点,可能多数使用的都是和q里介绍的类似的Ҏ?br />
Cookie的构?br />
Cookies最初设计时Q是ZCGI~程。但是,我们也可以用Javascript脚本来操Ucookies。在本文里,我们演C如何用Javascript脚本来操Ucookies?如果有需求,我可能会在以后的文章里介l如何用Perlq行cookie理。但是如果实在等不得Q那么我现在教你一手:仔细看看CGI.pm。在q个CGI包里有一个cookie()函数Q可以用它徏立cookie。但是,q是让我们先来介lcookies的本质?br />
在Javascript脚本里,一个cookie 实际是一个字W串属性。当你读取cookie的值时Q就得到一个字W串Q里面当前WEB用的所有cookies的名U和倹{每个cookie除了name名称和valueD两个属性以外,q有四个属性。这些属性是Q?expiresq期旉?path路径?domain域、以?secure安全?br />
Expires – q期旉。指定cookie的生命期。具体是值是q期日期。如果想让cookie的存在期限超q当前浏览器会话旉Q就必须使用q个属性。当q了到期日期Ӟ览器就可以删除cookie文gQ没有Q何媄响?br />
Path – 路径。指定与cookie兌的WEBc值可以是一个目录,或者是一个\径。如果http://www.zdnet.com/devhead/index.html 建立了一个cookieQ那么在http://www.zdnet.com/devhead/目录里的所有页面,以及该目录下面Q何子目录里的面都可以访问这个cookie。这是_在http://www.zdnet.com/devhead/stories/articles 里的M面都可以访问http://www.zdnet.com/devhead/index.html建立的cookie。但是,如果http://www.zdnet.com/zdnn/ 需要访问http://www.zdnet.com/devhead/index.html讄的cookesQ该怎么办?q时Q我们要把cookies 的path属性设|成“/”。在指定路径的时候,凡是来自同一服务器,URL里有相同路径的所有WEB面都可以共享cookies。现在看另一个例子:如果惌 http://www.zdnet.com/devhead/filters/ 和http://www.zdnet.com/devhead/stories/׃ncookiesQ就要把path设成“/devhead”?br />
Domain – 域。指定关联的WEB服务器或域。值是域名Q比如zdnet.com。这是对path路径属性的一个g伸。如果我们想?catalog.mycompany.com 能够讉Kshoppingcart.mycompany.com讄的cookiesQ该怎么? 我们可以把domain属性设|成“mycompany.com”Qƈ把path属性设|成“/”。FYIQ不能把cookies域属性设|成与设|它的服务器的所在域不同的倹{?br />
Secure – 安全。指定cookie的值通过|络如何在用户和WEB服务器之间传递。这个属性的值或者是“secure”Q或者ؓI。缺省情况下Q该属性ؓI,也就是用不安全的HTTPq接传递数据。如果一?cookie 标记为secureQ那么,它与WEB服务器之间就通过HTTPS或者其它安全协议传递数据。不q,讄了secure属性不代表其他Z能看C机器本地保存的cookie。换句话_把cookie讄为secureQ只保证cookie与WEB服务器之间的数据传输q程加密Q而保存在本地的cookie文gq不加密。如果想让本地cookie也加密,得自己加密数据?br />
操纵Cookies
误住,cookie是文档的一个字W串属性。要保存cookieQ只要徏立一个字W串Q格式是name=<value>Q名Uͼ|Q然后把文档?document.cookie 讄成与它相{即可。比如,假设想保存表单接收到的用户名Q那么代码看hpq样Q?br />
document.cookie = "username" + escape(form.username.value);
在这里,使用 escape() 函数非常重要Q因为cookie值里可能包含分号、逗号或者空根{这是_在读取cookie值时Q必M用对应的unescape()函数lD码?br />
我们当然q得介绍cookie的四个属性。这些属性用下面的格式加到字W串值后面:
name=<value>[; expires=<date>][; domain=<domain>][; path=<path>][; secure]
名称=<?gt;[; expires=<日期>][; domain=<?gt;][; path=<路径>][; 安全]
<value>, <date>, <domain> ?<path> 应当用对应的值替换?lt;date> 应当使用GMT格式Q可以用Javascript脚本语言的日期类Date?toGMTString() Ҏ得到q一GMT格式的日期倹{方括号代表q项是可选的。比如在 [; secure]两边的方括号代表要想把cookie讄成安全的Q就需要把"; secure" 加到cookie字符串值的后面。如?; secure" 没有加到cookie字符串后面,那么q个cookie是不安全的。不要把括?lt;> 和方括号[] 加到cookie里(除非它们是某些值的内容Q。设|属性时Q不限属性,可以用Q何顺序设|?br />
下面是一个例子,在这个例子里Qcookie "username" 被设|成?5分钟之后q期Q可以被服务器上的所有目录访问,可以?mydomain.com"域里的所有服务器讉KQ安全状态ؓ安全?br />
// Date() 的构造器讄以毫Uؓ单位
// .getTime() Ҏq回旉Q单位ؓ毫秒
// 所以要讄15分钟到期Q要?0000毫秒?5分钟
var expiration = new Date((new Date()).getTime() + 15 * 60000);
document.cookie = "username=" + escape(form.username.value)+ "; expires ="
+ expiration.toGMTString() + "; path=" + "/" + "; _
domain=" + "mydomain.com" + "; secure";
dcookies值有点象个小把戏Q因Z一ơ就得到了属于当前文档的所有cookies?br />
// 下面q个语句d了属于当前文档的所有cookies
var allcookies = document.cookie;
现在Q我们得解析allcookies变量里的不同cookiesQ找到感兴趣的指定cookie。这个工作很单,因ؓ我们可以利用Javascript语言提供的扩展字W串支持?br />
如果我们对前面分配的cookie "username" 感兴,可以用下面的脚本来读取它的倹{?br />
// 我们定义一个函敎ͼ用来d特定的cookie倹{?br />
function getCookie(cookie_name)
?br />
var allcookies = document.cookie;
var cookie_pos = allcookies.indexOf(cookie_name);
// 如果扑ֈ了烦引,׃表cookie存在Q?br />
// 反之Q就说明不存在?br />
if (cookie_pos != -1)
?br />
// 把cookie_pos攑֜值的开始,只要l值加1卛_?br />
cookie_pos += cookie_name.length + 1;
var cookie_end = allcookies.indexOf(";", cookie_pos);
if (cookie_end == -1)
?br />
cookie_end = allcookies.length;
?br />
var value = unescape(allcookies.substring(cookie_pos, cookie_end));
?br />
return value;
?br />
// 调用函数
var cookie_val = getCookie("username");
上面例程里的 cookie_val 变量可以用来生成动态内容,或者发送给服务器端CGI脚本q行处理。现在你知道了用Javascript脚本操纵cookies的基本方法。但是,如果你跟我一P那么我们要做的第一件事Q就是徏立一些接口函敎ͼ把cookies处理上的ȝ隐藏h。不q,在你开始编E之前,E候片刅R这些工作,早就有h替你做好了。你要做的,只是到哪Lq些接口函数而已?br />
比如Q在David Flangan的Javascript: The Definitive Guide 3rd Ed.q本书里Q可以找到很好的cookie应用cR你也可以在Oreilly的WEB站点上找到这本书里的例子。本文最后的链接列表里,有一些访问这些cookieCZ的直接链接?br />
Cookies 怪兽
因ؓ某些原因Cookies 的名声很不好。许多h利用cookies做一些卑鄙的事情Q比如流量分析、点击跟t。Cookies 也不是非常安全,特别是没有secure属性的cookies。不q,即你用了安全的cookiesQ如果你和别人共用计机Q比如在|吧Q那么别人就可以H探计算机硬盘上未加密保存的cookie文gQ也有可能H取你的敏感信息。所以,如果你是一个WEB开发h员,那么你要认真考虑q些问题。不要滥用cookies。不要把用户可能认ؓ是敏感的数据保存在cookies里。如果把用户的社会保险号、信用卡L保存在cookie里,{于把这些敏感信息放在窗L下,无异于把用户投到极大危险之中。一个好的原则是Q如果你不想陌生Z解你的这些信息,那就不要把它们保存在cookies里?br />
另外Qcookiesq有一些实际的限制。Cookies保留在计机上,不跟着用户走。如果用h换计机Q那么新计算机无法得到原来的cookie。甚至用户在同一台计机上用不同浏览器Q也得不到原来的cookieQNetscape 不能dInternet Explorer 的cookies?br />
q有Q用户也不愿意接受cookies。所以不要以为所有的览器都能接受你发出的cookies。如果浏览器不接受cookiesQ你要保证自qWEB站点不致因此而崩溃或中断?br />
另外WEB 览器能保留的cookies不一定能过300个。也没有标准规定览器什么时候、怎么样作废cookies。所以达到限制时Q浏览器能够有效地随机删除cookies。浏览器保留的来自一个WEB服务器上的cookiesQ不过20个,每个cookie的数据(包括名称和|Q不过4K字节?不过Q本文里的cookie寸没问题,它只占了12 K字节Q保存在3? cookies里?
而言之,注意保持cookie单。不要依赖cookies的存在,不要在每个cookie里保存太多信息。不要保存太多的cookes。但是,抛除q些限制Q在技巧高的WEB理员手里,cookie的概忉|一个有用的工具?br />
外部链接
每个 Javascript E序员都应当有一份JavascriptQ?David Flanagan 的The Definitive Guide?q本书里扑ֈcookie cME可以帮助你把不止一个变量编码到单一的cookieQ克服掉“每个WEB服务?0 个cookies的限?#8221;。请点击q个链接下蝲该例E,ftp://ftp.oreilly.com/pub/examples/nutshell/javascript/?br />
]]>
另一文章介l的一U方法:
var shrinkfactor=5
// left and top position of the thumbnailimage
// (distance to the left and top browser-margin, pixels)
var thumbleft = 30
var thumbtop = 30
// left and top position of the zoomed image
// (distance to the left and top browser-margin, pixels)
var largeleft = 300
var largetop = 30
// width and height of the enlarged image's sector (visible part, pixels)
var clipwidth = 240
var clipheight = 160
</SCRIPT>
<SCRIPT>
var isNav, isIE
var offsetX, offsetY
var selectedObj
var largewidth = 0
var largeheight = 0
var thumbwidth = Math.floor(largewidth/shrinkfactor)
var thumbheight = Math.floor(largeheight/shrinkfactor)
var dragimgwidth = Math.floor(clipwidth/shrinkfactor)
var dragimgheight = Math.floor(clipheight/shrinkfactor)
var dragimgleft = thumbleft+3
var dragimgtop = thumbtop+3
var difleft= largeleft-thumbleft
var diftop= largetop-thumbtop
var clippoints
var cliptop=0
var clipbottom=cliptop+clipheight
var clipleft=0
var clipright=clipleft+clipwidth
if (parseInt(navigator.appVersion) >= 4) {
if (navigator.appName == "Netscape") {
isNav = true
} else {
isIE = true
}
}
function setZIndex(obj, zOrder) {
obj.zIndex = zOrder
}
function shiftTo(obj, x, y) {
if (isNav) {
if(x<=document.thumb.left) {x=document.thumb.left}
if(x>=(document.thumb.left+thumbwidth-dragimgwidth-2)) {x=document.thumb.left+thumbwidth-dragimgwidth-2}
if(y<=document.thumb.top) {y=document.thumb.top}
if(y>=(document.thumb.top+thumbheight-dragimgheight-2)) {y=document.thumb.top+thumbheight-dragimgheight-2}
obj.moveTo(x,y)
} else {
if(x<=document.all.thumb.style.posLeft) {x=document.all.thumb.style.posLeft}
if(x>=(document.all.thumb.style.posLeft+thumbwidth-dragimgwidth-2)) {x=document.all.thumb.style.posLeft+thumbwidth-dragimgwidth-2}
if(y<=document.all.thumb.style.posTop) {y=document.all.thumb.style.posTop}
if(y>=(document.all.thumb.style.posTop+thumbheight-dragimgheight-2)) {y=document.all.thumb.style.posTop+thumbheight-dragimgheight-2}
obj.pixelLeft = x
obj.pixelTop = y
}
cliptop = (y-thumbtop)*shrinkfactor
clipbottom = cliptop+clipheight
clipleft = (x-thumbleft)*shrinkfactor
clipright = clipleft+clipwidth
if (document.all) {
clippoints ="rect("+cliptop+" "+clipright+" "+clipbottom+" "+clipleft+")"
document.all.large.style.posTop=largetop-cliptop
document.all.large.style.posLeft=largeleft-clipleft
document.all.large.style.clip=clippoints
}
if (document.layers) {
document.large.top=largetop-cliptop
document.large.left=largeleft-clipleft
document.large.clip.left = clipleft
document.large.clip.right = clipright
document.large.clip.top = cliptop
document.large.clip.bottom = clipbottom
}
}
function setSelectedElem(evt) {
if (isNav) {
var testObj
var clickX = evt.pageX
var clickY = evt.pageY
for (var i = document.layers.length - 1; i >= 0; i--) {
testObj = document.layers[i]
if ((clickX > testObj.left) &&
(clickX < testObj.left + testObj.clip.width) &&
(clickY > testObj.top) &&
(clickY < testObj.top + testObj.clip.height && document.layers[i].id=="dragimg")) {
selectedObj = testObj
setZIndex(selectedObj, 100)
return
}
}
} else {
var imgObj = window.event.srcElement
if (imgObj.parentElement.id.indexOf("dragimg") != -1) {
selectedObj = imgObj.parentElement.style
setZIndex(selectedObj,100)
return
}
}
selectedObj = null
return
}
function dragIt(evt) {
if (selectedObj) {
if (isNav) {
shiftTo(selectedObj, (evt.pageX - offsetX), (evt.pageY - offsetY))
} else {
shiftTo(selectedObj, (window.event.clientX - offsetX), (window.event.clientY - offsetY))
return false
}
}
}
function engage(evt) {
setSelectedElem(evt)
if (selectedObj) {
if (isNav) {
offsetX = evt.pageX - selectedObj.left
offsetY = evt.pageY - selectedObj.top
} else {
offsetX = window.event.offsetX
offsetY = window.event.offsetY
}
}
return false
}
function release(evt) {
if (selectedObj) {
setZIndex(selectedObj, 0)
selectedObj = null
}
}
function setNavEventCapture() {
if (isNav) {
document.captureEvents(Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP)
}
}
function init() {
if (document.layers) {
var imageurl=document.large.document.largepic.src
largewidth=document.large.document.width
largeheight=document.large.document.height
thumbwidth = Math.floor(largewidth/shrinkfactor)
thumbheight = Math.floor(largeheight/shrinkfactor)
document.thumb.document.write("<IMG NAME='thumbpic' SRC='"+imageurl+"' width="+thumbwidth+" height="+thumbheight+">")
document.thumb.document.close()
document.dragimg.document.write("<IMG NAME='dragimgpic' border=2 SRC='dragimg.gif' width="+dragimgwidth+" height="+dragimgheight+">")
document.dragimg.document.close()
document.large.left=largeleft
document.large.top=largetop
document.thumb.left=thumbleft
document.thumb.top=thumbtop
document.dragimg.left=dragimgleft
document.dragimg.top=dragimgtop
document.large.clip.left=clipleft
document.large.clip.right=clipright
document.large.clip.top=cliptop
document.large.clip.bottom=clipbottom
document.large.visibility="visible"
setNavEventCapture()
}
if (document.all) {
var imageurl=document.largepic.src
largewidth=document.all.large.offsetWidth
largeheight=document.all.large.offsetHeight
thumbwidth = Math.floor(largewidth/shrinkfactor)
thumbheight = Math.floor(largeheight/shrinkfactor)
thumb.innerHTML="<IMG NAME='thumbpic' SRC='"+imageurl+"' width="+thumbwidth+" height="+thumbheight+">"
dragimg.innerHTML="<IMG NAME='dragimgpic' border=2 SRC='http://www.jscode.cn/Uploadfile/200651515151450.GIF' width="+dragimgwidth+" height="+dragimgheight+">"
document.all.large.style.posLeft=largeleft
document.all.large.style.posTop=largetop
document.all.thumb.style.posLeft=thumbleft
document.all.thumb.style.posTop=thumbtop
document.all.dragimg.style.posLeft=dragimgleft
document.all.dragimg.style.posTop=dragimgtop
clippoints ="rect("+cliptop+" "+clipright+" "+clipbottom+" "+clipleft+")"
document.all.large.style.clip=clippoints
document.all.large.style.visibility="visible"
}
document.onmousedown = engage
document.onmousemove = dragIt
document.onmouseup = release
}
window.onload=init
</SCRIPT></head>
<body>
<p>用鼠标移动下面的ҎQ效果不错吧</p>
<center>
<DIV style="position:absolute;visibility:hidden;" ID="large"><IMG NAME="largepic" SRC="http://www.jscode.cn/Uploadfile/2006515151036789.JPG"></DIV>
<DIV style="position:absolute;" ID="thumb"></DIV>
<DIV style="position:absolute;" ID="dragimg"></DIV></center>
</body>
</html>