避免XXS攻击的字符转义(escape)和反转义(unescape)

escape和unescape

推荐看讶羽的这篇 underscore 系列之字符实体与 _.escape

这两个函数是为了转义以及反转义html字符串,替换&,<,>,',",和`字符为字符实体,防止浏览器误将其解释为标签,以避免XXS攻击.

我们要转义哪些字符呢?

  • < 和 > 因为浏览器会把它看成一个标签的开始或结束.

  • & 浏览器会认为&是一个字符实体的开始.例如&lt 浏览器会把它解释成<

  • ' 和 " 也需要注意, 例如

function reder(input){
    return '<input type="name" value=" '+input+' ''>'
}

//输入 "> <script>alert(1)</script>"
//return -> <input type="name" value=""><script>alert(1)</scripe>
  • ` 在IE低版本中(<=8),反引号可以用于关闭标签.

var escapeMap = {
            '&' : '&amp;',
            '<' : '&lt;',
            '>' : '&gt;',
            '"' : '&quot;',
            "'" : '&#x27;',
            '`' : '&#x60;'
    }
    //将对象的key和value反转
    _.invert = (obj)=>{
            var result = {};
            var keys = Object.keys(obj);
            for(var i = 0,len = keys.length ;i < len;i++){
                    result[obj[keys[i]]] = keys[i];
            }
            return result;
    }
    var unescapeMap = _.invert(escapeMap);
    //为了防止XXS攻击
    //转义HTML字符串,替换&,<,>,',"和`字符为字符实体
    //以及反转义
    //_.escape('Curly , Larry & Moe');
    //=>'Curly , Larry &amp; Moe'
    const createEscaper = (map) =>{
            var escaper = (match)=>map[match];
            var source = '(?:'+Object.keys(map).join('|')+')';
            //source = "(?:&|<|>|"|'|`)"
            //或者"(?:&amp;|&lt;|&gt;|&quot;|&#x27;|&#x60;)"
            var testRegexp = RegExp(source);
            //全局搜索,查找所有匹配项,而不是在第一个匹配项后停止
            var replaceRegexp = RegExp(source,'g');
            return (string)=>{
                    string = string == null ? '' : '' + string;
                    //replace 中第二个参数可以是个函数
                    return testRegexp.test(string) ? string.replace(replaceRegexp,escaper):string;
            }
    }

    _.escape = createEscaper(escapeMap);
    _.unescape = createEscaper(unescapeMap);

Last updated