聲明:以下僅爲簡單嘗試模塊,未經測試;如要使用,還請詳細斟酌。需要結合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); // 同時調用兩個