繁体   English   中英

转义用户生成的聊天消息,但渲染链接

[英]Escape user-generated chat messages but render links

用户输入聊天消息,使用Mustache模板直接呈现给页面。 显然,HTML应该被转义以防止HTML注入,但是再次链接应该呈现为<a href='...'>

我尝试使用{{{ ... }}}来返回未转义的HTML内容有不同的方法,这意味着链接将被呈现,我需要处理HTML转义自己。 有没有一种安全的方法可以做到这一点,而不依赖于我自己写的半生不熟的解决方案?

jQuery.text()会很棒,但我猜它会再次将<a>呈现为文本。

我还能在这做什么?

如果您不想编写自己的转义或解析解决方案,可以使用jQuery插件来处理名为Linkify的链接。 您可以简单地转义消息,然后在客户端解析它们。

它的工作原理示例:

var text = "<div>Test<br>Test<br>Test http://stackoverflow.com</div>";
$('div').text(text);

// Before: &lt;div&gt;Test&lt;br&gt;Test&lt;br&gt;Test http://stackoverflow.com&lt;/div&gt;

$('div').linkify();

// After: lt;div&gt;Test&lt;br&gt;Test&lt;br&gt;Test <a href="http://stackoverflow.com" class="linkified" target="_blank">http://stackoverflow.com</a>&lt;/div&gt;

只是一个想法:你可以建立自己的转义功能

escape : function () {
    return function(val, render) {
        var $s = $(val);
        var $elements = $s.find("*").not("a"); //add other white-listed elements seperated by comma 
        for (var i = $elements.length - 1; i >= 0; i--) {
            var e = $elements[i];
            $(e).replaceWith(e.innerHTML);
        }
        return $s.html();
    }
}

你可以通过调用函数

{{#escape}}{{{YOUR_TEXT}}}{{/escape}}

我没有测试过这个。 这个解决方案需要jQuery。 上面的代码基于以下解决方案: https//stackoverflow.com/a/27764431/1479486

首先尝试在.text()中插入,然后使用regexp渲染与.html()的链接。 在这里你可以看到一个香草的例子:

var a="see formula a<b>c in http://test.com or https://x.com?p=3";

var hold=document.createElement('div');
hold.textContent=a;

hold.innerHTML=hold.innerHTML.replace(
    /(https?:\/\/[-$A-Za-z0-9%_?&.~+\/=]+)/g,
    '<a href="$1">$1</a>'
);

window.addEventListener('load',function(){
    document.body.appendChild(hold);
});

对于更精确的正则表达式,您可以在这里看到

如果你最终走下正则表达式路线,那么下面的过滤器和正则表达式是我发现的用于拾取用户将尝试输入的各种网址的最具侵略性的过滤器和正则表达式。

下面是一个正在使用它的regexr: http ://regexr.com/3bjk9

(function () {
    'use strict';

    angular
        .module('core.filters')
        .filter('urlToA', urlToA);

    // --------------------

    function urlToA () {
        return function (string, noClick) {
            var urlPattern = /((?:(http|https|Http|Https|rtsp|Rtsp):\/\/(?:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,64}(?:\:(?:[a-zA-Z0-9\$\-\_\.\+\!\*\'\(\)\,\;\?\&\=]|(?:\%[a-fA-F0-9]{2})){1,25})?\@)?)?((?:(?:[a-zA-Z0-9][a-zA-Z0-9\-]{0,64}\.)+(?:(?:aero|arpa|asia|a[cdefgilmnoqrstuwxz])|(?:biz|b[abdefghijmnorstvwyz])|(?:cat|com|coop|c[acdfghiklmnoruvxyz])|d[ejkmoz]|(?:edu|e[cegrstu])|f[ijkmor]|(?:gov|g[abdefghilmnpqrstuwy])|h[kmnrtu]|(?:info|int|i[delmnoqrst])|(?:jobs|j[emop])|k[eghimnrwyz]|l[abcikrstuvy]|(?:mil|mobi|museum|m[acdghklmnopqrstuvwxyz])|(?:name|net|n[acefgilopruz])|(?:org|om)|(?:pro|p[aefghklmnrstwy])|qa|r[eouw]|s[abcdeghijklmnortuvyz]|(?:tel|travel|t[cdfghjklmnoprtvwz])|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw]))|(?:(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(?:25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])))(?:\:\d{1,5})?)(\/(?:(?:[a-zA-Z0-9\;\/\?\:\@\&\=\#\~\-\.\+\!\*\'\(\)\,\_])|(?:\%[a-fA-F0-9]{2}))*)?(?:\b|$)/gi; // jshint ignore:line

            return string ? string.replace(urlPattern, replace) : string;

            function replace (url) {
                var httpUrl = url.indexOf('http') === -1 ? 'http://' + url : url;

                if (noClick) {
                    return '<a>' + url + '</a>';
                } else {
                    return '<a href="' + httpUrl + '">' + url + '</a>';
                }
            }
        };
    }

})();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM