大家可能在填写完用户名或者密码时因为某种原因未登录而离开,这时大家可能因为密码框的星号而麻痹大意:以为密码不会被窥视,而放心离开。但是有一种软件可以直接查看星号隐藏下的密码原文,这就带来些安全隐患。不过本脚本可以让你的表单的密码区躲开密码星号查看软件的查看。
原理:生成一个ID为随机的隐藏Input,通过onkeyup事件实时捕获按键,并且复制到这个隐藏的Input里,同时将原密码区的值以“*”号替换掉。发送表单时,将隐藏Input的密码原文复制到原密码区并且销毁这个ID随机的隐藏Input。
下面注解如果在描述上有什么不妥欢迎提出
代码:
/*
基于表单防止星号查看器的脚本
作者:oror@Blueidea
邮箱:pcn88#hotmail.com
网站:www.wyev.com
*/
var aKey=new Array();
//用于保存随机隐藏Input的ID值
var aPrt=new Array();
//用于保存所有受保护Input的name值
var szFrm;
//用于保存表单名
frmProt={
/*
获得ID对应对象
szID:[字符串]对象ID属性
*/
$:function (szID){
return document.getElementById(szID);
},
/*
获得表单域对象
szFrmName:[字符串]表单的name值
*/
$v:function (szFrmName){
return document.forms[szFrmName];
},
/*
获得表单域的Input标签对象
szName:[字符串]标签的name值
szFrmName:[字符串]表单的name值
*/
$f:function (szName,szFrmName){
return frmProt.$v(szFrmName).elements[szName];
},
/*
绑定事件
obj:[OBJECT]对象
evn:[字符串]事件名称
f:函数
*/
fAttach:function (obj,evn,f){
if(!obj)return ;
if(obj.attachEvent){
obj.attachEvent("on"+evn,f);
}
if(obj.addEventListener){
obj.addEventListener(evn,f,false);
}
},
/*
获得随机数字
dwIn:[数字]随机范围
*/
fRand:function (dwIn){
return Math.floor(Math.random()*dwIn);
},
/*
获得随机字母与数字组合
dwLen:[数字]返回值长度
*/
fRandom:function (dwLen){
var dwDx,szResult="",szTmp;
var aMySd=new Array();
//建立数组用于保存随机字符,这里分成3组
aMySd[0]="abcdefghijklmnopqrstuvwxyz";
//第一组[0]:小写字母
aMySd[1]="0987654321";
//第二组[1]:数字
aMySd[2]=aMySd[0].toUpperCase();
//第三组[2]:大写字母
for(var i=0;i<dwLen;i++){
//依长度循环
dwDx=frmProt.fRand(3);
//获得一个随机数,范围0~2
szTmp=aMySd[dwDx];
//取出一组
szResult+=szTmp.substr(frmProt.fRand(szTmp.length),1);
//随机取出这一组中某个字符
}
return szResult;
},
/*
建立标签函数
szTarget:[字符串]父标签。生成的新标签将置于其中
szType:[字符串]要生成的标签类型
aProp:[数组]属性设置,如 Array("type=text","size=20")
*/
fCreateTarget:function (szTarget,szType,aProp){
var aTmp;
var objLocation=frmProt.$v(szTarget);
//获得父标签对象
var objPreCreate=document.createElement(szType);
//初始标签
for(var i=0;i<aProp.length;i++){
//设置属性循环开始
aTmp=aProp[i].split("=");
//按=号分开
if(aTmp.length<2){
//注意为避免设置错误,这里做个判断
alert("错误的属性值设定");
return ;
}
objPreCreate.setAttribute(aTmp[0],aTmp[1]);
//设置属性
}
objLocation.appendChild(objPreCreate);
//建立这个标签
},
/*
销毁标签
szTarget:[字符串]要销毁标签的父标签
szID:[字符串]要销毁标签ID
*/
fRemoveTarget:function (szTarget,szID){
var objLocation=frmProt.$v(szTarget);
//获得父标签对象
objLocation.removeChild(frmProt.$(szID));
},
/*
创建隐藏Input标签
szBase:[字符串]父标签。生成的Input标签将置于其中
szName:[字符串]Input标签的name属性
*/
fCreateHidden:function (szBase,szName){
var aHide=new Array("type=hidden","id="+szName,"value=");
//设置属性
frmProt.fCreateTarget(szBase,"input",aHide);
//调用fCreateTarget创建
},
/*获得event事件,主要为了兼容FireFox浏览器*/
fGetEvent:function (){
var objCaller=frmProt.fGetEvent.caller;
var objEvent,objResult=null;
while(objCaller!=null)
{
objEvent=objCaller.arguments[0];
if(objEvent)objResult=objEvent;
objCaller=objCaller.caller;
}
return objResult;
},
/*
获得按键
*/
fGetKey:function (){
var e=frmProt.fGetEvent();
var dwKey=window.event?e.keyCode:e.which;
return dwKey;
},
/*
入口函数
szFrmName:[字符串]表单名
szProtName:[字符串]要保护的Input名,格式 "password|password2" 多个请用"|"分开
*/
Init:function (szFrmName,szProtName){
aPrt=szProtName.split("|");
//将受保护Input名分组
var dwGetLen=aPrt.length;
//获得分组长度
var objPas;
if(dwGetLen<1)return ;
//如果长度为0则中止
for(var i=0;i<dwGetLen;i++){
//循环
aKey[i]=frmProt.fRandom(frmProt.fRand(64)+1);
//随机英文和数字,长度范围1~63
frmProt.fCreateHidden(szFrmName,aKey[i]);
//创建隐藏Input表单
objPas=frmProt.$f(aPrt[i],szFrmName);
//获得受保护Input对象
if(objPas==null)return ;
//获取失败,则中止
objPas.value="";
frmProt.fAttach(objPas,"keyup",frmProt.fTask);
//绑定onkeyup事件到受保护Input
}
frmProt.fAttach(frmProt.$v(szFrmName),"submit",frmProt.fSub);
//绑定onsubmit到form表单
szFrm=szFrmName;
//将传入的表单名赋给全局变量
},
//提交表单触发函数:将隐藏Input的内容复制到受保护Input里,销毁隐藏Input
fSub:function (){
for(var i=0;i<aPrt.length;i++){
frmProt.$f(aPrt[i],szFrm).value=frmProt.$(aKey[i]).value;
//将隐藏Input的内容复制到受保护Input里
frmProt.fRemoveTarget(szFrm,aKey[i]);
//销毁隐藏Input
}
return true;
},
//Input实时保护函数
fTask:function (){
var dwKeyCode,szPrt,szOrg,szTemp,dwSta,szA,szB,objMouse;
dwKeyCode=frmProt.fGetKey();
if(dwKeyCode!=37&&dwKeyCode!=39){
//判断并且过滤掉光标左右移动按键,否则光标会受selection.createRange影响
for(var i=0;i<aPrt.length;i++){
if(!frmProt.$(aKey[i])){
//判断一下隐藏Input是否存在。
alert("隐藏域已经销毁,请重新加载本页!");
return ;
}
szPrt=frmProt.$f(aPrt[i],szFrm).value;
//得到受保护Input的Value值
szOrg=frmProt.$(aKey[i]).value;
//得到隐藏Input的Value值
if(szPrt!=""){
//如果不为空
dwSta=szOrg.length-szPrt.length;
if(dwSta==1){
//这里主要判断删除字符
if(document.all){
//IE
objMouse=document.selection.createRange();
//作用:定位光标
objMouse.setEndPoint("StartToStart",frmProt.$f(aPrt[i],szFrm).createTextRange());
dwSta=objMouse.text.length;
//获得光标的位置
}else {
//FireFox
objMouse=frmProt.$f(aPrt[i],szFrm).selectionStart;
dwSta=objMouse;
}
szA=szOrg.substr(0,dwSta);
//从第一个字符截取到光标位置长度的字符串。
szB=szOrg.substr(dwSta+1,szOrg.length);
//从光标位置并且跳掉一个字符截取到整个字符串长度的字符,这里实现删除字符。
frmProt.$(aKey[i]).value=szA+szB;
//组成新的字符串并拷贝到隐藏的Input
}else if(dwSta>1){
//这里由于无法对于连续删除按键进行判断,于是发现用户这样操作,则重置表单
frmProt.$(aKey[i]).value="";
frmProt.$f(aPrt[i],szFrm).value="";
}else {
szTemp=szPrt.replace(/\*/g,"");
//替换掉所有*获得插入字符
dwSta=szPrt.indexOf(szTemp);
//判断最新插入字符的位置
szA=szOrg.substr(0,dwSta);
//从第一个字符截取到这个插入字符的位置
szB=szOrg.substr(dwSta,szPrt.length);
//从这个插入字符位置截取到字符串最后
frmProt.$(aKey[i]).value=szA+szTemp+szB;
//组成新的字符串并拷贝到隐藏的Input
frmProt.$f(aPrt[i],szFrm).value=szPrt.replace(/./ig,"*");
//替换掉受保护Input的值为*
}
}else {
frmProt.$(aKey[i]).value="";
//如果受保护Input值为空,清空隐藏Input的值
}
}
}
}
}
调用方式
window.onload=function(){
frmProt.Init("表单名","要保护的密码区域,多个请用‘|’分隔");
}
演示HTML
[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]
测试接收的ASP
<%
Dim szFrm
For Each szFrm In Request.Form
Response.Write szFrm & "=" & Request.Form(szFrm) & "<br />"
Next
%>
目前只支持单个表单域中的一个或者多个input标签。
这里还可以扩展一下,比如说随机生成一串字符作为密匙,用密匙实时加密密码原文。然后发送到服务器端,由服务器端根据密匙解密密码原文。
由于本人能力有限,如果上述代码有什么错误或者你有更好的实现代码欢迎交流!谢谢!!