Кодирование и URL-адреса HTML

#.net #regex #escaping #html-encode #linkify

#.net #регулярное выражение #экранирование #html-кодирование #linkify

Вопрос:

У меня есть строка ввода, которая должна быть удалена из HTML-кодов, поэтому я использую значение по умолчанию.Функция Net .HtmlEncode() для экранирования всех опасных символов.

Теперь я пытаюсь заменить URL-адреса во входной строке на привязки HREF с помощью регулярного выражения.

Проблема в том, что когда я «связываю» URL-адрес перед вызовом.HtmlEncode() теги привязки теряются, что логично. Но когда я делаю linkify ПОСЛЕ вызова.HtmlEncode (), некоторые URL-адреса искажаются, потому что они содержат опасные символы?

Похоже, проблема с куриным яйцом, как ее решить?

Пример:

Строка ввода:

See http://example.com/q=1amp;x=2

Ожидаемый результат:

See <a
href="http://example.com/q=1amp;x=2">http://example.com/q=1amp;amp;x=2</a>

Сначала выполняем HtmlEncode, после чего вызываем Linkify:

See <a
href="http://example.com/q=1amp;amp;x=2">http://example.com/q=1amp;amp;x=2</a>

Сначала делаем Linkify, после чего вызываем HtmlEncode:

See amp;<a
href=amp;quot;http://example.com/q=1amp;amp;x=2amp;quot;amp;>http://example.com/q=1amp;amp;x=2amp;</aamp;>

Решение, которое я использую в настоящее время, заключается в вызове.HtmlDecode() для всех совпадений, найденных регулярным выражением (linkify), но это не на 100% надежно, поскольку допустимый URL-адрес теоретически может содержать шаблон, подобный amp;amp; которому, который будет декодирован, но не должен.

Комментарии:

1. Возможно, включите простой пример? Неясно, что именно влечет за собой процесс компоновки.

2. Что это за утилита регулярных выражений «linkify»?

3. @JeremyStein Просто регулярное выражение, подобное этому: codinghorror.com/blog/2008/10/the-problem-with-urls.html

4. @Joshua в примере нет части замены. Это прекрасный способ сопоставления, но его недостаточно для замены. Я опубликую ответ…

Ответ №1:

Вы должны по-разному относиться к обычному тексту и ссылкам. Итак, сначала разделите входные данные на части:

 If you don't believe me that 1 < 2, see http://example.com/q=1amp;x=2
 

становится коллекцией с двумя членами:

 { "If you don't believe me that 1 < 2, see ", "http://example.com/q=1amp;x=2" }
 

Вы кодируете первый и создаете ссылку из второго, кодируя только текст ссылки:

 {
    "If you don't believe me that 1 amp;< 2, see ",
    "<a href="http://example.com/q=1amp;x=2">http://example.com/q=1amp;amp;x=2</a>"
}
 

Затем вы объединяете результаты в конечный результат.

Но, возможно, было бы лучше, если бы вы использовали библиотеку, созданную для создания HTML. Либо Html Agility Pack, либо ASP.NET , в зависимости от ваших потребностей.

Комментарии:

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

2. Я не понимаю, почему вы не можете использовать библиотеку?

3. Библиотека предназначена для синтаксического анализа ввода html, поэтому я не могу ее использовать, потому что мой ввод представляет собой обычный текст, он не должен содержать HTML. Единственное, что мне нужно сделать, это преобразовать (обычные текстовые) ссылки в html-привязки.

Ответ №2:

Похоже, что атака с использованием межсайтового скриптинга ожидает своего часа.

Тестовая ссылка на Google.

Большинство подходов, которые я видел, которые преобразуют пользовательский ввод в HTML-разметку, используют для этого какую-то «зарезервированную» пользовательскую последовательность, отличную от HTML, например, ссылка выше на самом деле выглядит так в редакторе переполнения стека:

 [Test link to google.][1]    

  [1]: http://www.google.com
 

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

Комментарии:

1. Я уже разрешаю стили шрифтов и разрывы строк с помощью ubb-кодов, таких как [b] для жирного шрифта и [br] для разрывов, поэтому я мог бы просто добавить [url] в качестве требования к URL-адресам, но это помогло бы только найти URL-адреса в обычном тексте, а не предотвратить HtmlEncode() от того, чтобы все испортить 😉 Я мог бы временно закодировать их с помощью чего-то вроде Base64, выполнить HtmlEncode, а затем откодировать их обратно, но это не похоже на правильное решение.

2. Я читал книгу по Drupal и обнаружил, что существует псевдостандарт того, что я назвал «зарезервированной пользовательской последовательностью, отличной от HTML» — BBCode. Я быстро выполнил поиск .NET BBCode и получил следующее: eksith.wordpress.com/2009/01/14/aspnet-bbcode-c На этой странице также есть ссылка под названием «лучшая альтернатива», которая соответствует решению, которое вы ищете.

Ответ №3:

Вы не можете сделать это с помощью замены регулярных выражений. Вам нужно запустить атрибут href через urlencode, а текст ссылки — через htmlencode.

Комментарии:

1. Мое текущее решение — запустить HtmlEncode() в строке, выполнить RegEx.Replace() и запустить HtmlDecode в HREF. Это работает в 99% случаев, но теоретически существует вероятность того, что действительная ссылка содержит параметры, закодированные в HTML, которые не следует декодировать. Но я никогда раньше не видел такого URL-адреса 😉

2. Я не понимаю, как вы можете писать код для идентификации атрибутов href для вызова HtmlDecode, но вы не можете написать код для идентификации ссылок и их правильной обработки.

3. Возможно, я бы понял, если бы вы показали нам код, который вы используете.