Безопасные символы для дружественного URL [закрыто]

168

Мне нужно сделать сайт, на котором будут статьи, и я хотел бы сделать для него понятные URL-адреса, например URL-адрес страницы с

Название: Статья Тест

должны стать: http://www.example.com/articles/article_test.

Конечно, мне нужно удалить некоторые символы из названия, например ?или #, но я не уверен, какие из них удалить.

Может кто-нибудь сказать мне, какие символы безопасно хранить?

Пауло
источник
Был аналогичный вопрос, здесь . Проверьте это, вы также можете найти там несколько полезных ответов (их было довольно много).
Ладья

Ответы:

210

Процитируем раздел 2.3 RFC 3986 :

«Символы, которые разрешены в URI, но не имеют зарезервированной цели, называются незарезервированными. Они включают в себя прописные и строчные буквы, десятичные цифры, дефис, точку, подчеркивание и тильду».

ALPHA  DIGIT  "-" / "." / "_" / "~"

Обратите внимание, что в RFC 3986 указано меньше зарезервированных знаков препинания, чем в более раннем RFC 2396 .

Пропустить голову
источник
@Skip Head, «символы» включают латинские символы, такие как çи õ?
Мохамад
6
@ Мохамад: Нет, только ASCII, хотя поддержка UTF-8 улучшается.
Дитрих Эпп
@Dietrich Epp, спасибо. Я думаю, это не должно иметь значения, если URL предназначен для оформления и в целях SEO, например: www.mysite.com/[postId]/post-title-with-ç-and-õ
Мохамад
1
@Mohamad: последняя часть там будет изменена под капотом post-title-with-%C3%A7-and-%C3%B5, но она все равно будет отображаться в строке адреса пользователя как post-title-with-ç-and-õ.
Дитрих Эпп
7
Ваши читатели португальцы, поэтому используйте португальские символы.
Дитрих Эпп
107

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

В зарезервированные символы:

  • амперсанд ("&")
  • доллар ("$")
  • знак плюс ("+")
  • запятая (",")
  • косая черта ("/")
  • двоеточие (":")
  • точка с запятой (";")
  • равно ("=")
  • вопросительный знак ("?")
  • Символ «В» («@»)
  • фунт ("#").

Знаки, которые обычно считаются небезопасными :

  • пространство (" ")
  • меньше чем и больше чем ("<>")
  • открывать и закрывать скобки ("[]")
  • открывать и закрывать фигурные скобки ("{}")
  • труба ("|")
  • обратная косая черта ("\")
  • каретка ("^")
  • процентов ("%")

Возможно, я забыл один или несколько, что приводит меня к повторению ответа Карла V. В долгосрочной перспективе вам, вероятно, лучше использовать «белый список» разрешенных символов и затем кодировать строку, а не пытаться идти в ногу с символами, которые запрещены серверами и системами.

Gary.Ray
источник
#является зарезервированным символом, используемым для закладок на определенной странице, созданный с помощью одного HTML-элемента с соответствующим атрибутом name или id (sans #-symbol).
TheLonelyGhost
Спасибо - я обновил ответ.
Gary.Ray
Знак вопроса отображается здесь как зарезервированный и небезопасный - я думаю, что он только зарезервированный, но я могу ошибаться
Джонатан Бэйзил
6
Другие, похоже, не согласны с тем, что тильда ~небезопасна. Вы уверены, что это так?
DRS
3
Белый список не так хорош, если работать с другими языками, кроме английского. У Unicode слишком много точек кода ОК. Поэтому внесение в черный список небезопасных, вероятно, будет проще всего реализовать в регулярных выражениях.
Патанджали
41

Лучше всего хранить только некоторые символы (белый список) вместо удаления определенных символов (черный список).

Технически вы можете разрешить любой символ, если вы правильно его закодировали. Но, чтобы ответить в духе вопроса, вам следует разрешить только следующие символы:

  1. Строчные буквы (конвертировать строчные в нижние)
  2. Числа от 0 до 9
  3. Тире - или подчеркивание _
  4. Тильда ~

Все остальное имеет потенциально особое значение. Например, вы можете подумать, что можете использовать +, но его можно заменить пробелом. & также опасен, особенно если использовать некоторые правила перезаписи.

Как и в случае с другими комментариями, ознакомьтесь со стандартами и спецификациями для получения полной информации.

деревенщина
источник
15
Я обнаружил, что предварительным периодом является неправильный выбор символа для URL-безопасного кодера Base64, потому что будут те редкие случаи, когда ваши закодированные данные могут давать две последовательные точки (".."), что существенно в что это относится к родительскому каталогу.
Пол
5
@pohl: это проблема только в том случае, если ваш URL-адрес используется в качестве пути к файлу, либо в вашем коде, либо если ваш веб-сервер на самом деле пытается сопоставить URL-адрес с файлами перед пересылкой запроса в сценарий (к сожалению, очень часто).
Андре Карон
4
На самом деле, в нашем случае использовать его в качестве пути к файлу было бы нормально, поскольку в файлах unix разрешено иметь несколько и даже последовательные точки в именах. Для нас проблема возникла в инструменте мониторинга под названием Site Scope, в котором есть ошибка (возможно, наивное регулярное выражение), и она сообщала о ложных ложных простоях. Для нас мы застряли на старой версии Site Scope, команда администраторов отказывается платить за обновление, и один очень важный клиент имеет Site Scope (не эквивалентный), записанный в их контракт. По общему признанию, большинство не окажется в моих ботинках.
Пол
8
Слава богу, что кто-то опубликовал список без особого бреда. Что касается точки (.) - как сказал @pohl, не используйте ее! Вот еще один странный случай с IIS (не знаю, происходит ли это на других веб-серверах): если он находится в конце вашего URL, вы, скорее всего, получите ошибку 404 (он попытается найти [/ pagename] . страница)
nikib3ro
34

Всегда безопасно

Они безопасны (в теории / спецификации), в основном везде, кроме доменного имени.
Процентное кодирование ничего не указано, и вы готовы.

    A-Z a-z 0-9 - . _ ~ ( ) ' ! * : @ , ;

Иногда безопасно

Безопасно только при использовании в определенных компонентах URL; используйте с осторожностью.

    Paths:     + & =
    Queries:   ? /
    Fragments: ? / # + & =
    

Никогда не безопасно

Согласно спецификации URI (RFC 3986) все остальные символы должны быть в процентах. Это включает:

    <space> <control-characters> <extended-ascii> <unicode>
    % < > [ ] { } | \ ^
    

Если важна максимальная совместимость, ограничьте кодировку AZ az 0-9 - _.
(с периодами только для расширений файлов).

Держите контекст в уме

Даже если он действителен для каждой спецификации, URL-адрес может быть «небезопасным», в зависимости от контекста. Например, file: /// URL-адрес, содержащий недопустимые символы имени файла, или компонент запроса, содержащий «?», «=» И «&», если они не используются в качестве разделителей. Правильная обработка этих случаев, как правило, зависит от ваших сценариев и может быть обойдена, но об этом нужно помнить.

Beejor
источник
Не могли бы вы предоставить какие-либо источники для вашего второго требования («Иногда безопасно»)? В частности, я считаю, что вы ошибаетесь, говоря, что =это небезопасно для запросов. Например, FIQL принимает знаки равенства и описывает себя как «дружественный к URI» и «оптимизированный и предназначенный для использования в компоненте запроса». В моей интерпретации RFC 3986 явно разрешает "=", "&", "+" и другие в запросах.
DanielM
@DanielM "?", "=" И "&" допустимы в запросах по спецификации, хотя на практике они широко используются для анализа пар имя-значение в запросе. Таким образом, они могут быть небезопасными как часть самих имен / ценностей. Является ли это «небезопасным» или нет, может быть вопросом мнения.
Beejor
Некоторые источники по запросу. (1) RFC 3986, раздел 3.4: «[...] компоненты запроса часто используются для передачи идентифицирующей информации в виде пар« ключ = значение »[...]» (2) WhatWG URL Spec, Sec. 6.2: «Построить и структурировать объект URLSearchParams довольно просто: [...] params.toString() // "key=730d67"» (3) PHP Manual, http-build-query: «Создать строку запроса в кодировке URL. [...] Приведенный выше пример выведет: 0=foo&1=bar[...](4) Дж. Старр, Perishable Press: «При создании веб-страниц часто необходимо добавлять ссылки, которые требуют параметризованных строк запроса».
Beejor
@Beejor: я создаю URL и использую '-' и ';' во время строительства. Это не веб-приложение, а мобильное приложение. Не веб-разработчик и, следовательно, буду ли я в безопасности, если я использую два вышеупомянутых символа в свойстве Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen Это действительные символы URL. Хотя, если используется для ссылки на пути в локальной файловой системе, имейте в виду, что некоторые системы запрещают определенные символы в именах файлов. Например, «file: /// path / to / my: file.ext» будет недопустимым на Mac.
Beejor
17

Рассматривая RFC3986 - Унифицированный идентификатор ресурса (URI): общий синтаксис , ваш вопрос вращается вокруг компонента пути URI.

    foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment
      |   _____________________|__
     / \ /                        \
     urn:example:animal:ferret:nose

Ссылаясь на раздел 3.3, допустимые символы для URI segmentимеют тип pchar:

pchar = незарезервировано / pct-закодировано / под-разделы / ":" / "@"

Который распадается на:

ALPHA / DIGIT / "-" / "." / "_" / "~"

pct-encoded

"!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="

":" / "@"

Или другими словами: Вы можете использовать любую (не управления-) символ из таблицы ASCII , за исключением / , ?, #, [и ].

Это понимание поддерживается RFC1738 - Унифицированные указатели ресурсов (URL) .

Philzen
источник
2
Это отличный пример теоретически правильного ответа, который приводит к проблемам применительно к реальному миру, в котором мы на самом деле живем. Это правда, что большинство из этих персонажей не будут вызывать проблемы большую часть времени. Но в реальном мире существуют такие вещи, как прокси-серверы, маршрутизаторы, шлюзы, ретрансляторы и т. Д., Которые «любят» проверять URL-адреса и взаимодействовать с ними таким образом, который не учитывает теоретический стандарт. Чтобы избежать этих ловушек, вы в значительной степени ограничены избеганием всего, кроме буквенно-цифровых символов, тире, подчеркивания и точки.
deltamind106
1
@ deltamind106 Можете ли вы предоставить примеры и / или ссылки, чтобы уточнить, какие из этих символов безопасны в соответствии с RFC, на самом деле это не так? Я бы предпочел придерживаться фактов, подкрепленных стандартами, в своем ответе, и я с удовольствием обновлю свой ответ, если вы сможете точно определить факты, которыми я мог пренебречь.
Philzen
2
@ deltamind106 Я бы посоветовал нам попытаться заставить продукты соответствовать стандартам, а не указывать разработчикам не делать этого. Я считаю ваше предупреждение заслуженным, но мы должны внести свой вклад в сообщение о несоответствии поставщикам, если это необходимо.
Ло-Тан
@Philzen: я создаю URL и использую '-' и ';' во время строительства. Это не веб-приложение, а мобильное приложение. Не веб-разработчик и, следовательно, буду ли я в безопасности, если я использую два вышеупомянутых символа в свойстве Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen Да, конечно -и ;безопасно, это то, что мой ответ и RFC ясно заявляет.
Филзен
12

незарезервировано = ALPHA / DIGIT / "-" / "." / "_" / "~"

LKK
источник
3
Разве «АЛЬФА» не означает «ЦИФРА»? Я предполагаю, что АЛЬФА - это сокращение от «буквенно-цифровой», а буквенно-цифровой означает прописные, строчные и цифры.
Люк
11
На самом деле альфа не подразумевает буквенно-цифровой. Буква и цифра - это две разные вещи, а буквенно-цифровая - это сочетание этих вещей. Он мог бы написать свой ответ так: ALPHANUMERIC / "-" / "." / "_" / "~"
MacroMan
1
Нотация ABNF для «незарезервированных» в RFC 3986 перечисляет их отдельно.
Патанджали
11

Из контекста, который вы описываете, я подозреваю, что то, что вы на самом деле пытаетесь создать, называется «SEO-слаг». Лучшая общеизвестная практика для них:

  1. Преобразовать в нижний регистр
  2. Преобразуйте целые последовательности символов, отличных от az и 0-9, в один дефис (-) (не подчеркивание)
  3. Удалите «стоп-слова» из URL, т. Е. Не значащие индексируемые слова, такие как «a», «an» и «the»; Google "стоп-слова" для обширных списков

Так, в качестве примера, статья под названием «Использование! @% $ * Для представления ругательства в комиксах» получит фрагмент «Использование-представлять-ругаться-комиксы».

хаос
источник
Это действительно хороший подход, чтобы удалить эти «стоп-слова» из URL? Из-за этого поисковые системы будут наказывать сайт?
Пауло
Обычно считается, что поисковые системы признают только некоторую часть URL-адреса и / или уменьшают значимость последующих частей, поэтому при удалении стоп-слов вы максимизируете количество ключевых слов, встроенных в ваш URL, что у вас есть шанс на самом деле рейтинга на.
хаос
1
@chaos Вы все еще рекомендуете удалить StopWord, если учесть это: seobythesea.com/2008/08/google-stopword-patent Кроме того, можете ли вы порекомендовать хороший список стоп-слов? Это лучший список, который я нашел на данный момент - link-assistant.com/seo-stop-words.html
nikib3ro
@ kape123 Это не очень хороший список для меня. «c» и «d» являются языками программирования, и многие из этих других слов также выглядят значительными. Я бы, вероятно, просто лишил бы основных: a, и, on, of, или,,, с.
mpen
6

Формат для URI определен в RFC 3986 . Смотрите раздел 3.3 для деталей.

Joschi
источник
6

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

mpen
источник
3

У меня была похожая проблема, я хотел иметь красивые URL-адреса и пришел к выводу, что я должен разрешать только буквы, цифры и _ в URL-адресах. Это нормально, затем я написал несколько хороших регулярных выражений и понял, что он распознает все символы UTF8 не буквы в .NET и был испорчен. Кажется, это известная проблема для .NET regex engine. Итак, я получил это решение:

private static string GetTitleForUrlDisplay(string title)
{
    if (!string.IsNullOrEmpty(title))
    {
        return Regex.Replace(Regex.Replace(title, @"[^A-Za-z0-9_-]", new MatchEvaluator(CharacterTester)).Replace(' ', '-').TrimStart('-').TrimEnd('-'), "[-]+", "-").ToLower();
    }
    return string.Empty;
}


/// <summary>
/// All characters that do not match the patter, will get to this method, i.e. useful for unicode chars, because
/// .NET impl of regext do not handle unicode chars. So we use char.IsLetterOrDigit() which works nicely and we 
/// return what we approve and return - for everything else.
/// </summary>
/// <param name="m"></param>
/// <returns></returns>
private static string CharacterTester(Match m)
{
    string x = m.ToString();
    if (x.Length > 0 && char.IsLetterOrDigit(x[0]))
    {
        return x.ToLower();
    }
    else
    {
        return "-";
    }
}
Любомир Тошев
источник
3
.NET регулярные выражения поддерживают Unicode довольно хорошо на самом деле. Вы должны использовать классы символов Unicode, например, \ p {L} для всех букв. См. Msdn.microsoft.com/en-us/library/20bw873z.aspx#CategoryOrBlock
TheCycoONE
1

Я нашел очень полезным кодировать мой URL-адрес в безопасный, когда я возвращал значение через ajax / php в URL-адрес, который затем снова читался страницей.

Вывод PHP с кодировщиком URL для специального символа &

//PHP returning the sucess info of ajax request
echo "".str_replace('&','%26',$_POST['name'])." category was changed";

//javascript sending the value to url
window.location.href='time.php?return=updated&val='+msg;

//javascript/php executing the function printing the value of the url,
//now with the text normally lost in space because of the reserved & character.

setTimeout("infoApp('updated','<?php echo $_GET['val'];?>');",360);

Надеюсь, кто-нибудь найдет мои маленькие фрагменты кода полезными! :)

DIY-форум
источник
0

Я думаю, что вы ищете что-то вроде «URL Encoding» - кодирование URL, чтобы его можно было «безопасно» использовать в Интернете:

Вот ссылка для этого. Если вам не нужны специальные символы, просто удалите все, которые требуют кодировки URL:

http://www.w3schools.com/TAGS/ref_urlencode.asp

Энди Уайт
источник
-4

От 3 до 50 символов. Может содержать строчные буквы, цифры и специальные символы - точка (.), Тире (-), подчеркивание (_) и скорость (@).

Ramji
источник
4
Любая ссылка для этого?
Дакаб