在使用Javascript将其添加到DOM之前消毒用户输入

我正在为空闲时间正在编写的聊天应用程序编写JS,并且需要根据用户提交的数据改变HTML标识符。 通常情况下,这通常是一些不稳定的事情,我甚至不会去尝试,但是这次我没有看到自己有太多的选择。 然后我需要做的就是转义HTML标识以确保它不会允许XSS或破坏HTML。

代码如下:

var user_id = escape(id)
var txt = '<div class="chut">'+
            '<div class="log" id="chut_'+user_id+'"></div>'+
            '<textarea id="chut_'+user_id+'_msg"></textarea>'+
            '<label for="chut_'+user_id+'_to">To:</label>'+
            '<input type="text" id="chut_'+user_id+'_to" value='+user_id+' readonly="readonly" />'+
            '<input type="submit" id="chut_'+user_id+'_send" value="Message"/>'+
          '</div>';

逃避id以避免上述任何问题的最佳方法是什么? 正如你所看到的,现在我正在使用内置的escape()函数,但是我不确定这应该与其他替代方法相比有多好。 我大多习惯于在输入到文本节点之前对输入进行清理,而不是一个id本身。


切勿使用escape() 。 这与HTML编码无关。 这更像URL编码,但它甚至不适合。 这是一个奇怪的非标准编码,只能在JavaScript中使用。

如果你想要一个HTML编码器,你必须自己写,因为JavaScript不会给你一个。 例如:

function encodeHTML(s) {
    return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/"/g, '&quot;');
}

然而,尽管这足以将您的user_id放置在input value ,但对于id来说这还不够,因为ID只能使用有限的字符选择。 (并且%不在其中,所以escape()或甚至encodeURIComponent()不好。)

您可以创建自己的编码方案,将任何字符放入ID中,例如:

function encodeID(s) {
    if (s==='') return '_';
    return s.replace(/[^a-zA-Z0-9.-]/g, function(match) {
        return '_'+match[0].charCodeAt(0).toString(16)+'_';
    });
}

但是,如果相同的user_id发生两次,则仍然存在问题。 说实话,扔掉HTML字符串的整个过程通常是一个糟糕的主意。 改为使用DOM方法,并保留对每个元素的JavaScript引用,这样就不必一直调用getElementById ,也不必担心如何将任意字符串插入到ID中。

例如。:

function addChut(user_id) {
    var log= document.createElement('div');
    log.className= 'log';
    var textarea= document.createElement('textarea');
    var input= document.createElement('input');
    input.value= user_id;
    input.readonly= True;
    var button= document.createElement('input');
    button.type= 'button';
    button.value= 'Message';

    var chut= document.createElement('div');
    chut.className= 'chut';
    chut.appendChild(log);
    chut.appendChild(textarea);
    chut.appendChild(input);
    chut.appendChild(button);
    document.getElementById('chuts').appendChild(chut);

    button.onclick= function() {
        alert('Send '+textarea.value+' to '+user_id);
    };

    return chut;
}

您也可以使用便捷函数或JS框架来减少那里的创建集附加调用的冗长度。

ETA:

我目前使用jQuery作为框架

好的,然后考虑jQuery 1.4创建快捷方式,例如:

var log= $('<div>', {className: 'log'});
var input= $('<input>', {readOnly: true, val: user_id});
...

我现在面临的问题是,我使用JSONP将元素和事件添加到页面,因此在显示消息之前我不知道元素是否已经存在。

您可以在JavaScript中查找user_id元素节点(或包装器对象),以节省将该信息放入DOM本身,其中可以放入id的字符受到限制。

var chut_lookup= {};
...

function getChut(user_id) {
    var key= '_map_'+user_id;
    if (key in chut_lookup)
        return chut_lookup[key];
    return chut_lookup[key]= addChut(user_id);
}

_map_前缀是因为JavaScript对象不像任意字符串的映射那样工作,空字符串和IE中的某些Object成员名称会混淆)。


我喜欢的另一种方法是使用本地DOM功能:http://shebang.brandonmintern.com/foolproof-html-escaping-in-javascript


你可以使用一个简单的正则表达式来声明该id只包含允许的字符,如下所示:

if(id.match(/^[0-9a-zA-Z]{1,16}$/)){
    //The id is fine
}
else{
    //The id is illegal
}

我的示例只允许字母数字字符和长度为1到16的字符串,您应该将其更改为与您使用的id类型相匹配。

顺便说一句,在第6行,value属性缺少一对引号,这是在两个级别引用时容易犯的错误。

我看不到您的实际数据流,取决于上下文,可能根本不需要该检查,或者可能不够。 为了做出适当的安全审查,我们需要更多的信息。

一般来说,关于建立逃生或消毒功能,不要盲目信任他们。 你需要确切地知道他们做了什么,并且你需要确定这实际上是你需要的。 如果它不是你所需要的,那么你的代码就是你自己的,大多数情况下,像我给你的简单的白名单正则表达式工作得很好。

链接地址: http://www.djcxy.com/p/19389.html

上一篇: Sanitizing user input before adding it to the DOM in Javascript

下一篇: Select checkbox when clicking in textarea (JavaScript?)