Является косой чертой ( "/" ), эквивалентной закодированной косой чертой ( "% 2F" ) в части пути HTTP-URL
У меня есть сайт, который обрабатывает "/" и "% 2F" в части пути (а не в строке запроса) URL-адреса по-разному. Это плохо, что нужно делать в соответствии с RFC или реальным миром?
Я спрашиваю, потому что я постоянно испытываю небольшие сюрпризы в используемой веб-инфраструктуре (Ruby on Rails), а также в слоях ниже (Passenger, Apache, например, мне пришлось включить "ALLOW_ENCODED_SLASHES" для Apache). Я теперь склоняюсь к тому, чтобы полностью избавиться от закодированных косечек, но мне интересно, должен ли я записывать отчеты об ошибках, где я вижу странное поведение, связанное с закодированными косыми чертами.
Что касается того, почему у меня есть кодированные косые черты, в основном у меня есть такие маршруты, как это:
:controller/:foo/:bar
где: foo - это что-то вроде пути, который может содержать слэши. Я подумал, что наиболее простой задачей было бы просто вывести URL foo
, чтобы косые черты игнорировались механизмом маршрутизации. Теперь у меня возникают сомнения, и довольно ясно, что фреймворки на самом деле не поддерживают это, но, согласно RFC, неправильно это делать?
Вот некоторая информация, которую я собрал:
RFC 1738 (URL):
Обычно URL-адрес имеет ту же интерпретацию, когда октет представлен символом и когда он кодируется. Однако это не относится к зарезервированным символам: кодирование символа, зарезервированного для конкретной схемы, может изменить семантику URL-адреса.
RFC 2396 (URI):
Эти символы называются "зарезервированными", поскольку их использование в компоненте URI ограничено их зарезервированной целью. Если данные для компонента URI будут конфликтовать с зарезервированной целью, тогда конфликтующие данные должны быть экранированы перед формированием URI.
(может ли экранирование означать нечто иное, чем кодирование зарезервированного символа?)
RFC 2616 (HTTP/1.1):
Символы, отличные от символов в "зарезервированных" и "небезопасных" наборах (см. RFC 2396 [42]), эквивалентны их "% HEX HEX".
Существует также этот отчет об ошибках для Rails, где они, похоже, ожидают, что закодированная косая черта будет вести себя по-другому:
Правильно, я ожидаю разные результаты, потому что они указывают на разные ресурсы.
Он ищет литеральный файл 'foo/bar' в корневом каталоге. Неэкранированная версия ищет файловую панель в каталоге foo.
Из RFC ясно, что raw vs. encoded является эквивалентом для безоговорочных символов, но какова история зарезервированных символов?
Ответы
Ответ 1
Из собранных вами данных я бы сказал, что закодированные "/" в uri означают, что они снова будут отображаться как "/" на уровне приложения /cgi.
Чтобы сказать, что если вы используете apache с mod_rewrite
, например, он не будет соответствовать шаблону, ожидающему слэш в URI с закодированными косыми чертами.
Однако, как только соответствующий модуль /cgi/... вызывается для обработки запроса, он выполняет его для декодирования и, например, извлекает параметр, включая косые черты, в качестве первого компонента URI.
Если ваше приложение затем использует эти данные для извлечения файла (чье имя файла содержит косую черту), возможно, это плохо.
Подводя итог, я считаю совершенно нормальным видеть разницу в поведении в "/" или "% 2F", поскольку их интерпретация будет выполняться на разных уровнях.
Ответ 2
У меня также есть сайт с многочисленными URL-адресами с символами urlencoded. Я нахожу, что многие веб-API (в том числе инструменты Google для веб-мастеров и несколько модулей Drupal) обходятся по URL-адресам. Многие API-интерфейсы автоматически декодируют URL-адреса в какой-то момент своего процесса, а затем используют результат как URL-адрес или HTML. Когда я нахожу одну из этих проблем, я обычно дважды кодирую результаты (что превращает% 2f в% 252f) для этого API. Однако это нарушит другие API, которые не ожидают двойного кодирования, поэтому это не универсальное решение.
Лично я избавляюсь от как можно большего числа специальных символов в своих URL-адресах.
Кроме того, я использую номера id в своих URL-адресах, которые не зависят от urldecoding:
example.com/blog/my-amazing-blog%2fstory/yesterday
становится:
example.com/blog/12354/my-amazing-blog%2fstory/yesterday
в этом случае мой код использует только 12354 для поиска статьи, а остальная часть URL-адреса игнорируется моей системой (но по-прежнему используется для SEO). Кроме того, этот номер должен появиться ПЕРЕД неиспользованным компонентом URL. Таким образом, URL-адрес будет работать, даже если% 2f будет неправильно декодироваться.
Кроме того, не забудьте использовать канонические теги, чтобы ошибки URL не переводились в дублированный контент.
Ответ 3
История %2F
vs /
заключалась в том, что согласно первоначальной рекомендации W3C, слэша "должна подразумевать иерархическую структуру":
Пример 2
URI
http://www.w3.org/albert/bertram/marie-claude
и
http://www.w3.org/albert/bertram%2Fmarie-claude
НЕ идентичны, так как во втором случае закодированная косая черта не имеют иерархическое значение.
Ответ 4
Если вы используете Tomcat, добавьте '-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH = true' в свойствах VM.
https://tomcat.apache.org/tomcat-7.0-doc/config/systemprops.html#Security
Ответ 5
Что делать, если :foo
в своей естественной форме содержит косые черты? Вы бы этого не хотели. Разве это не отличие, которое эта рекомендация пытается сохранить? Он специально отмечает,
Сходство с условными обозначениями имен файлов операционной системы unix и других дисковых систем должно рассматриваться как чисто случайное и не должно быть указано, что URI следует интерпретировать как имена файлов.
Если кто-то создавал онлайновый интерфейс для программы резервного копирования и хотел выразить путь как часть пути URL, было бы целесообразно кодировать косые черты в пути к файлу, так как это не является частью иерархия ресурса - и, что более важно, маршрут. /backups/2016-07-28content//home/dan/
теряет корень файловой системы в двойной косой чертой. Выйти из косой черты - это подходящий способ отличить, как я ее прочитал.