Должен принимать URL-адреса, которые используются на практике, а не только URL-адреса, соответствующие стандарту
На самом деле спецификация URI довольно либеральна и допускает конструкции, которые обычно нужно исключать по причинам совместимости...
Я хочу принять http://fr.wikipedia.org/wiki/Français,, что является нестандартным
Это не URI, но равно вполне стандартный IRI .
- нестандартный, потому что шестнадцатеричное кодирование процентов должно быть в верхнем регистре
- нестандартно, потому что фрагмент фрагмента (из '# 'в конце) не должен включать'? '
Оба они вполне приемлемы в соответствии со стандартом URI.RFC 3986 рекомендует, но не требует, чтобы верхний регистр использовался при создании процентных кодировок.
Я могу запретить 'javascript:' и разрешить все остальное;если вы думаете, что это может поставить под угрозу безопасность, скажите, пожалуйста.
Так и будет.К сожалению, в пространство имен схемы URI было внесено несколько потенциально опасных дополнений, и они, несомненно, будут и в будущем.Кроме того, существуют потенциальные возможности для обхода черных списков с использованием закодированных и управляющих символов.
Кроме того, сопоставление с произвольной схемой означает, что ваша вторичная цель обнаружения адресов в тексте приведет к ложному срабатыванию в большинстве случаев, когда двоеточиеused.
Белый список является единственным вероятным способом продвижения вперед, поэтому вам просто нужно вручную разрешить каждую новую схему в каждом конкретном случае.Это требует некоторой осторожности;например, схема data:
кажется безвредной и полезной, но потенциально страдает теми же проблемами XSS, что и javascript:
.
. Вам также потребуется знать некоторую информацию о каждой схеме.Такие схемы, как http
и ftp
, имеют «полномочия по присвоению имен на основе сервера»: они могут включать в себя отдельное имя хоста и путь к ресурсу внутри этого хоста;Кроме того, вы, вероятно, требуете, чтобы они были абсолютными URI.Если вы хотите разрешить файловые URI, вам нужно убедиться, что они не содержат хостов (file:///
).Для других схем может не быть конкретного синтаксиса, требуемого самим стандартом URI, но могут быть и другие ограничения, например, mailto:
должен принимать действительный адрес электронной почты.
Гигантское регулярное выражение (IСпросите себя, могут ли все браузеры и фреймворки, которые я использую, обрабатывать этот размер), который выглядит очень всеобъемлющим
Это не сработает в JavaScript, поскольку имеет неподдерживаемый синтаксис \x{code point}
.Также такие языки, как JavaScript, чьи движки регулярных выражений работают в терминах кодовых единиц UTF-16 вместо полных кодовых точек Unicode, не смогут обрабатывать диапазоны символов вне BMP.
Вам придется заменить длинный \x{A0}...\x{1FFFD}
группирует что-то более простое, например \u00A0-\uFFFD
, а затем проверяет наличие недопустимых суррогатных пар отдельно, а также несимвольных символов 0xnnFFFE – F, если вы заботитесь о них (вероятно, нет).
Возможно, вы захотитевероятно, уже удалили все плохие суррогаты и не-символы на общем уровне сканирования ввода, прежде чем вы дойдете до проверки IRI;нет никаких оснований разрешать их при любом вводе текста.Выполнение этого на отдельном шаге имеет больше смысла, чем попытка объединить все в одно регулярное выражение.
С заменой самой длинной части этого регулярного выражения является безумно длинная строка проверки цифр, пытающаяся проверить числовой IPадреса.Это то, что регулярные выражения вообще не годятся.Я бы настоятельно рекомендовал не беспокоиться о числовых адресах IPv6 и IPv-future: даже при условии широкого распространения IPv6 в ближайшее время никто не будет использовать их в обозримом будущем.(Вы даже хотите разрешить ссылки на числовые адреса? Зависит от того, что делает ваше приложение, но часто нет.)
Вы также можете запретить использование префиксов userinfo @ hostname (поскольку они традиционно бесполезны, кроме атак спуфинга), и имен хостов в процентах (поскольку они не служат цели, учитывая наличие Punycode, и не работают в некоторых браузерах).
Таким образом, нет единого ответа на проверку IRI, но вот то место, с которого вы могли бы начать:
(
https?://
(
([0-9]{1-3}(\.[0-9]{1-3}){3})|
([-0-9a-z\u00A0-\uFFFD]{1-63}(\.[-0-9a-z\u00A0-\uFFFD]{1-63})*)
)
(:[0-9]+)?/
(
%[0-9a-f][0-9a-f]|
[-._!$&'()*+,:;=@~0-9a-z\u00A0-\uFFFD/?#]
)*
)|(
ftp:// // same again but with no ?query
... // or port number
)|(
mailto: // specify requirements for
... // other accepted schemes
)
(предполагается нечувствительность к регистру. При этом применяются ограничения DNS, которые не являются частьюсамой спецификации URI, хотя и не полностью, так как она не проверяет начальное / конечное значение -
в метках DNS или диапазон номеров в октетах IPv4. Проверка адресов электронной почты оставлена читателю как упражнениесама по себе трудная задача, не подходящая для регулярных выражений, если вы хотите выполнять ее строго.)