Безопасно ли двоеточие `:` для использования дружественных URL-адресов?

109

Мы разрабатываем систему URL-адресов, которая будет указывать разделы приложения как слова, разделенные косой чертой. В частности, это GWT, поэтому соответствующие части URL-адреса будут в хэше (который будет интерпретироваться уровнем контроллера на стороне клиента):

http://site/gwturl#section1/section2

Некоторым разделам могут потребоваться дополнительные атрибуты, которые мы хотели бы указать с помощью :, чтобы части URL-адреса были однозначными. Код будет сначала разбит на /, а затем на :следующее:

http://site/gwturl#user:45/comments

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

http://site/gwturl#user%3A45/comments <--- BAD

Безопасно ли использование двоеточия таким образом (я имею в виду, что оно не будет автоматически закодировано) для браузеров, систем закладок, даже для кода Javascript или Java?

Николь
источник
Может быть, было бы лучше указать (более четко), что вы используете URL-адреса только на стороне клиента? Поскольку многие ответы (как и мой), похоже, предполагают, что вы собираетесь отправить URL-адрес на сервер с помощью HTTP.
Veger
Отредактировано, чтобы добавить пояснение, что использование фрагмента происходит на стороне клиента.
Николь
Мне любопытно: после 10 месяцев эта схема URL-адресов сработала для вас? Я подумываю использовать ту же схему.
Джонатан Суинни,
1
@Jonathan Swinney, К сожалению, я ушел из этого проекта (и компании), хотя ответы здесь убедили меня, что это правильный путь. Если бы я начал новый проект, я бы использовал эту схему, но я также обязательно использовал бы, #!чтобы указать, что страницы сохраняют состояние - см. Googlewebmastercentral.blogspot.com/2009/10/… (Это предложение было соблюдено интенсивными пользователями AJAX, такими как Facebook)
Николь,
Я только что узнал, что WhatsApp будет вырезать URL-адрес по первому двоеточию, поэтому, например, он сделал URL-адрес карт Google бесполезным. Так что да, важно избежать этого.
Петруза

Ответы:

84

Недавно я написал кодировщик URL, так что это довольно свежо в моей памяти.

http://site/gwturl#user:45/comments

Все символы в части фрагмента ( user:45/comments) совершенно допустимы для URI RFC 3986 .

Соответствующие части ABNF :

fragment      = *( pchar / "/" / "?" )
pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
pct-encoded   = "%" HEXDIG HEXDIG
sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
                 / "*" / "+" / "," / ";" / "="

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


РЕДАКТИРОВАТЬ:

Ооо!

Несмотря на мои утверждения о спецификации URI, безоговорочный дает правильный ответ, когда указывает, что спецификация HTML 4 ограничивает имена / идентификаторы элементов .

Обратите внимание, что правила идентификаторов меняются в HTML 5 . Ограничения URI по-прежнему будут применяться (на момент написания есть некоторые нерешенные проблемы, связанные с использованием URI в HTML 5).

Макдауэлл
источник
Я думаю, вы кое-что поняли, не могли бы вы объяснить это немного подробнее? Не отправить это на сервер не проблема, поскольку мы используем GWT. Я просто не уверен, что мне понятен синтаксис, указанный в процитированном вами разделе.
Николь
Но :это разделитель, а не разделитель.
bobince
1
Точка с запятой является допустимой для pchar, поэтому вопрос о том, находится ли она в sub-delim или gen-delim,
Вегер,
@bobince - :это внутри pchar, что внутри fragment, поэтому :разрешено. @Renesis - В Википедии есть статья о ABNF en.wikipedia.org/wiki/ABNF Вы в основном смотрите на список разрешенных символов, где /означает ИЛИ . Я не занимался программированием GWT, поэтому не знаю, как он использует фрагментную часть URI.
McDowell
И последний вопрос: есть ли у вас представление о реальном применении этой спецификации? Означает ли это, что браузеры должны / будут игнорировать (пропускать кодировку) :во фрагменте?
Николь
59

В дополнение к анализу Макдауэлла по стандарту URI помните также, что фрагмент должен быть допустимым именем привязки HTML. Согласно http://www.w3.org/TR/html4/types.html#type-name

Жетоны ID и NAME должны начинаться с буквы ([A-Za-z]) и могут сопровождаться любым количеством букв, цифр ([0-9]), дефисами ("-"), подчеркиванием ("_"). , двоеточия (":") и точки (".").

Так что вам повезло. ":" явно разрешено. И никто не должен "%" - экранировать его не только потому, что "%" здесь недопустимый символ, но также потому, что фрагмент должен соответствовать имени привязки char-by-char, поэтому ни один агент не должен пытаться каким-либо образом вмешиваться в них.

Однако вы должны это проверить. Веб-стандарты не соблюдаются строго, иногда стандарты противоречат друг другу. Например, HTTP / 1.1 RFC 2616 не допускает строку запроса в URL-адресе запроса, тогда как HTML создает ее при отправке формы с помощью метода GET. То, что реализовано в реальном мире, в конце концов, выигрывает.

бесспорный
источник
58

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

например http://en.wikipedia.org/wiki/Template:Welcome

Пол Рэй
источник
31
Самый актуальный ответ. Все мы знаем, что то, что указано в спецификациях, имеет мало общего с реальностью веб-разработки. Вы не получите лучшей гарантии «безопасности», чем «это делает один из 10 лучших веб-сайтов в мире».
Стивен Коллинз
1
@StevenCollins Не более актуален, чем ответ, данный за 3 года до этого, который утверждает то же самое :)
Мартин Джеймс,
7

Я бы не стал на это рассчитывать. Скорее всего, он будет закодирован как %3Aмногие пользовательские агенты.

Асаф
источник
1
@arbales: Да. Некоторые менее совместимые пользовательские агенты будут оставлять несовместимые URL-адреса без украшений.
Асаф,
4

Из URLEncoderjavadoc:

Дополнительные сведения о кодировке HTML-форм см. В спецификации HTML .

При кодировании строки применяются следующие правила:

  • Буквенно-цифровые символы от «a» до «z», от «A» до «Z» и от «0» до «9» остаются прежними.
  • Специальные символы «.», «-», «*» и «_» остаются прежними.
  • Пробел "" преобразуется в знак плюса "+".
  • Все остальные символы небезопасны и сначала преобразуются в один или несколько байтов с использованием некоторой схемы кодирования. Затем каждый байт представлен трехзначной строкой «% xy», где xy - двузначное шестнадцатеричное представление байта. Рекомендуемая схема кодирования - UTF-8. Однако из соображений совместимости, если кодировка не указана, используется кодировка платформы по умолчанию.

То :есть небезопасно.

axtavt
источник
3

Я не вижу, чтобы Firefox или IE8 кодировали некоторые URL-адреса Википедии , содержащие этот символ.

kprobst
источник
1
Opera также сохраняет точку с запятой, но рассчитывать на такое поведение - не лучший
вариант
1
Renesis говорит о фрагменте URL, а не о пути URL.
Gumbo
Когда я писал этот вопрос, я думал о Википедии. Тогда является ли использование двоеточия технически недействительным / небезопасным? Я обычно вижу (и) в закодированных URL-адресах Википедии, но никогда не вижу двоеточия, что меня немного смущает.
Николь
3
У Wayback Machine есть: во многих своих ссылках - например, web.archive.org/web/20080822150704/http://stackoverflow.com
barrowc
2

Двоеточие используются как разделение между именем пользователя и паролем, если протокол требует аутентификации.

JP Silvashy
источник
0

Колон небезопасен. Посмотреть здесь

Боб
источник
Эта страница не объясняет, почему они небезопасны. В упомянутом RFC2396 также не говорится, что этого следует избегать. Кроме того, предоставленный скрипт конвертера не кодирует его (по крайней мере, в Chrome 9).
Адам Линдберг
Адам, ты неправ. В нем прямо указано, что и почему.
ktamlyn 08
-5

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

Рик
источник