XSS简单防御模块

声明:以下仅为简单尝试模块,未经测试;如要使用,还请详细斟酌。需要结合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: "&nbsp", // space
        34: "&quot", // "
        38: "&amp;", // &
        39: "&#x27;", // '
        47: "&#x2F;", // /
        60: "&lt;", // <
        62: "&gt;",
        198: "&AElig;",
        193: "&Aacute;",
        194: "&Acirc;",
        192: "&Agrave;",
        197: "&Aring;",
        195: "&Atilde;",
        196: "&Auml;",
        199: "&Ccedil;",
        208: "&ETH;",
        201: "&Eacute;",
        202: "&Ecirc;",
        200: "&Egrave;",
        203: "&Euml;",
        205: "&Iacute;",
        206: "&Icirc;",
        204: "&Igrave;",
        207: "&Iuml;",
        209: "&Ntilde;",
        211: "&Oacute;",
        212: "&Ocirc;",
        210: "&Ograve;",
        216: "&Oslash;",
        213: "&Otilde;",
        214: "&Ouml;",
        222: "&THORN;",
        218: "&Uacute;",
        219: "&Ucirc;",
        217: "&Ugrave;",
        220: "&Uuml;",
        221: "&Yacute;",
        225: "&aacute;",
        226: "&acirc;",
        230: "&aelig;",
        224: "&agrave;",
        229: "&aring;",
        227: "&atilde;",
        228: "&auml;",
        231: "&ccedil;",
        233: "&eacute;",
        234: "&ecirc;",
        232: "&egrave;",
        240: "&eth;",
        235: "&euml;",
        237: "&iacute;",
        238: "&icirc;",
        236: "&igrave;",
        239: "&iuml;",
        241: "&ntilde;",
        243: "&oacute;",
        244: "&ocirc;",
        242: "&ograve;",
        248: "&oslash;",
        245: "&otilde;",
        246: "&ouml;",
        223: "&szlig;",
        254: "&thorn;",
        250: "&uacute;",
        251: "&ucirc;",
        249: "&ugrave;",
        252: "&uuml;",
        253: "&yacute;",
        255: "&yuml;",
        162: "&cent;",
        '\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; // 支持链式调用
        }
    }
}

使用方法

  1. 保护某个元素。
    初始化一个protect对象,调用bind方法,传入需要绑定dom的选择器;
    默认会绑定change事件,如需绑定其他事件,传入bind的第二个参数
var protect = new Protect()

protect.bind('input');
  1. 解除对某个元素的绑定。
protect.unbind(selector, eventType);
  1. 编码某个值。
var protect = new Protect();

protect.htmlEncode(val); // 编码html
protect.javaScriptEncode(val); // 编码js
protect.encode(val); // 同时调用两个
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值