声明:以下仅为简单尝试模块,未经测试;如要使用,还请详细斟酌。需要结合jquery使用。
模块代码
// ### protect.js ###
/**
* @desc 防止XSS攻击
* @date 2020-02-25
* @author Chang-Jin
*/
function Protect() {
var hex = new Array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
// charCode转换map
var charCodeMap = {
10: "<br/>", // newline
32: " ", // space
34: """, // "
38: "&", // &
39: "'", // '
47: "/", // /
60: "<", // <
62: ">",
198: "Æ",
193: "Á",
194: "Â",
192: "À",
197: "Å",
195: "Ã",
196: "Ä",
199: "Ç",
208: "Ð",
201: "É",
202: "Ê",
200: "È",
203: "Ë",
205: "Í",
206: "Î",
204: "Ì",
207: "Ï",
209: "Ñ",
211: "Ó",
212: "Ô",
210: "Ò",
216: "Ø",
213: "Õ",
214: "Ö",
222: "Þ",
218: "Ú",
219: "Û",
217: "Ù",
220: "Ü",
221: "Ý",
225: "á",
226: "â",
230: "æ",
224: "à",
229: "å",
227: "ã",
228: "ä",
231: "ç",
233: "é",
234: "ê",
232: "è",
240: "ð",
235: "ë",
237: "í",
238: "î",
236: "ì",
239: "ï",
241: "ñ",
243: "ó",
244: "ô",
242: "ò",
248: "ø",
245: "õ",
246: "ö",
223: "ß",
254: "þ",
250: "ú",
251: "û",
249: "ù",
252: "ü",
253: "ý",
255: "ÿ",
162: "¢",
'\r': "\r"
}
var thecharcharMap = {
'\n': "\\n", // newline
'\r': "\\r", // Carriage return
'\'': "\\'",
'"': "\\\"",
'\&': "\\&",
'\\': "\\\\",
'\t': "\\t",
'\b': "\\b",
'\f': "\\f",
'/': "\\x2F",
'<': "\\x3C",
'>': "\\x3E"
}
if (!Protect.prototype.escapeCharx) {
Protect.prototype.escapeCharx = function(original) {
var thechar = original.charCodeAt(0);
if (charCodeMap[thechar]) {
return charCodeMap[thechar];
} else {
if (thechar > 127) {
var c = thechar;
var a4 = c % 16;
c = Math.floor(c / 16);
var a3 = c % 16;
c = Math.floor(c / 16);
var a2 = c % 16;
c = Math.floor(c / 16);
var a1 = c % 16;
return "&#x" + hex[a1] + hex[a2] + hex[a3] + hex[a4] + ";";
}
return original;
}
}
Protect.prototype.changeTo16Hex = function(charCode) {
return "\\x" + charCode.charCodeAt(0).toString(16);
}
Protect.prototype.encodeCharx = function(original) {
var thecharchar = original.charAt(0);
var thechar = original.charCodeAt(0);
if (thecharcharMap[thecharchar]) {
return thecharcharMap[thecharchar];
} else {
if (thechar > 47 && thechar < 58) { // 数字
return original;
}
if (thechar > 64 && thechar < 91) { // 大写字母
return original;
}
if (thechar > 96 && thechar < 123) { // 小写字母
return original;
}
if (thechar > 127) { // 大于127用unicode
var c = thechar;
var a4 = c % 16;
c = Math.floor(c / 16);
var a3 = c % 16;
c = Math.floor(c / 16);
var a2 = c % 16;
c = Math.floor(c / 16);
var a1 = c % 16;
return "\\u" + hex[a1] + hex[a2] + hex[a3] + hex[a4] + "";
} else {
return this.changeTo16Hex(original);
}
}
}
Protect.prototype.htmlEncode = function(str) { // HTML转码
var preescape = str;
var escaped = "";
for (var i = 0; i < preescape.length; i++) {
var p = preescape.charAt(i);
escaped = escaped + this.escapeCharx(p);
}
return escaped;
}
// 使用“\”对特殊字符进行转义,除数字字母之外,小于127使用16进制“\xHH”的方式进行编码,大于用unicode(非常严格模式)。
Protect.prototype.javaScriptEncode = function(str) {
var preescape = str;
var escaped = "";
var i = 0;
for (i = 0; i < preescape.length; i++) {
escaped = escaped + this.encodeCharx(preescape.charAt(i));
}
return escaped;
}
// 联合使用HTML和JavaScript编码
Protect.prototype.encode = function(str) {
return this.htmlEncode(this.javaScriptEncode(str));
}
/**
* 对被保护对象的val值进行编码
* 防止xss攻击
*
* @param {*} protectedSelector 被保护对象的选择器
* @param {*} eventType 被保护对象在什么事件类型下触发保护
*/
Protect.prototype.bind = function(protectedSelector, eventType) {
var self = this;
eventType = eventType || 'change'; // 默认绑定change事件
$(document).on(eventType + '.xss', protectedSelector, function() {
var $this = $(this);
var val = $this.val();
var tagReg = /<[\S\s]*>/;
if (val.match(tagReg)) {
val = self.htmlEncode(val);
} else {
val = self.javaScriptEncode(val);
}
$this.val(val);
})
return this; // 支持链式调用
}
// 解除保护
Protect.prototype.unbind = function(protectedSelector, eventType) {
eventType = eventType || 'change'; // 默认绑定change事件
$(document).off(eventType + '.xss', protectedSelector);
return this; // 支持链式调用
}
}
}
使用方法
- 保护某个元素。
初始化一个protect对象,调用bind方法,传入需要绑定dom的选择器;
默认会绑定change事件,如需绑定其他事件,传入bind的第二个参数
var protect = new Protect()
protect.bind('input');
- 解除对某个元素的绑定。
protect.unbind(selector, eventType);
- 编码某个值。
var protect = new Protect();
protect.htmlEncode(val); // 编码html
protect.javaScriptEncode(val); // 编码js
protect.encode(val); // 同时调用两个