2016-02-19 2 views
4

Как я могу идти о заменяя string:Замените строку эквивалентом HTML. Помимо <a> тегов

Hello my name is <a href='/max'>max</a>! 
<script>alert("DANGEROUS SCRIPT INJECTION");</script> 

с

Hello my name is <a href='/max'>max</a>! 
&lt;script&gt;alert("DANGEROUS SCRIPT INJECTION");&lt;/script&gt; 

Я могу легко иметь все <, > заменен &lt;, &gt; с:

string = string.replace(/</g, "&lt;").replace(/>/g, "&gt;"); 

но я все еще хочу иметь <a> ссылки.


Я также посмотрел в предотвращении инъекции сценария с:

var html = $(string.bold()); 
html.find('script').remove(); 

Но я хочу, чтобы иметь возможность по-прежнему читать теги сценария, а не их удаления.

+0

Лучше не допускать HTML-код в строке и иметь предопределенный формат для вставки ссылок, аналогично тому, как это делает SO (например, '[linktext] (http://linkurl.com) '). Таким образом, вы не имеете HTML-кода в строке и имеете полный контроль над тем, что добавляется. –

+1

@RajaprabhuAravindasamy, который не является дубликатом - он удаляет * все * HTML из строки. OP ищет, чтобы сохранить элементы 'a' (и, предположительно, и другие) –

+0

@RoryMcCrossan А, я вижу. Я пропустил это чтение. –

ответ

0

. Один из подходов к этой проблеме - использовать регулярное выражение со строгим шаблоном обратного просмотра, который позволяет очень близко привязывать якоря, которые следуют определенному формату.

Допустим, вы хотите разрешить только ссылки, которые точно следуют этому примеру:

<a href="http://host.domain/path?query#anchor">text</a> 

и

<a href="https://host.domain/path?query#anchor">text</a> 

Построить регулярное выражение, которое соответствует только «<» символы, которые не следуют этим действительный образец (отрицательный lookbehind):

<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>) 

Одна из проблем с этим регулярным выражением состоит в том, что если вы сопоставляете его со всей строкой, < по-прежнему будет соответствовать закрывающему элементу a (</a>), поэтому, если вы замените каждое совпадение на &lt;, вы в конце концов сломаете якорь.

Вы можете разрешить все закрывающие теги </a> путем добавления альтернативу негативный взгляд-за:

<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>) 

Может быть кто-то еще лучшее решение для этой проблемы к югу.

Вот окончательный string.replace:

string.replace(/<(?!a href="https?:\/\/\w[\w.-\/\?#]+">\w+<\/a>|\/a>)/g, '&lt;'); 

Примечание: Все эти входные проверки всегда должны быть сделаны на стороне сервера, на стороне клиента проверка может просто обойти, и вы будете на ваш сервер попадают вредоносные данные, несмотря на проверку.

0

Этот фрагмент кода должен сделать трюк. Вы можете добавить дополнительные имена тегов, которые вы хотите передать как теги HTML в массиве allowedTagNames.

// input 
var html = "Hello my name is <a href='/max'>max</a>! <script>alert('DANGEROUS SCRIPT INJECTION');</script>"; 

var allowedTagNames = ["a"]; 
// output 
var processedHTML = ""; 

var processingStart = 0; 
// this block finds the next tag and processes it 
while (true) { 
    var tagStart = html.indexOf("<", processingStart); 
    if (tagStart === -1) { break; } 

    var tagEnd = html.indexOf(">", tagStart); 
    if (tagEnd === -1) { break; } 

    var tagNameStart = tagStart + 1; 
    if (html[tagNameStart] === "/") { 
     // for closing tags 
     ++tagNameStart; 
    } 
    // we expect there to be either a whitespace or a > after the tagName 
    var tagNameEnd = html.indexOf(" ", tagNameStart); 
    if (tagNameEnd === -1 || tagNameEnd > tagEnd) { 
     tagNameEnd = tagEnd; 
    } 

    var tagName = html.slice(tagNameStart, tagNameEnd); 
    // copy in text which is between this tag and the end of last tag 
    processedHTML += html.slice(processingStart, tagStart); 
    if (allowedTagNames.indexOf(tagName) === -1) { 
     processedHTML += "&lt;" + html.slice(tagStart + 1, tagEnd) + "&gt;"; 
    } else { 
     processedHTML += html.slice(tagStart, tagEnd + 1); 
    } 
    processingStart = tagEnd + 1; 
} 
// copy the rest of input which wasn't processed 
processedHTML += html.slice(processingStart); 

Примечание: это не будет работать, если есть < или > внутри свойства тега. Например: <a href=">">