Bezpieczne znaki dla przyjaznego adresu URL [zamknięte]

168

Muszę stworzyć stronę internetową, która będzie zawierała artykuły i chciałbym stworzyć dla niej przyjazne adresy URL, na przykład adres URL strony z

Tytuł: Test artykułu

powinny stać się: http://www.example.com/articles/article_test.

Oczywiście muszę usunąć niektóre znaki z tytułu, takie jak ?lub #, ale nie jestem pewien, które z nich usunąć.

Czy ktoś może mi powiedzieć, jakie postacie można bezpiecznie zachować?

Paulo
źródło
Było podobne pytanie, tutaj . Sprawdź to, możesz tam również znaleźć przydatne odpowiedzi (było ich całkiem sporo).
Rook

Odpowiedzi:

210

Cytując sekcję 2.3 RFC 3986 :

„Znaki, które są dozwolone w identyfikatorze URI, ale nie mają zarezerwowanego celu, nazywane są niezarezerwowanymi. Należą do nich wielkie i małe litery, cyfry dziesiętne, łącznik, kropka, podkreślenie i tylda”.

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

Zauważ, że RFC 3986 zawiera mniej zastrzeżonych znaków interpunkcyjnych niż starszy RFC 2396 .

Skip Head
źródło
@ Pomiń Head, czy „znaki” zawierają znaki zakodowane w alfabecie łacińskim, takie jak çi õ?
Mohamad
6
@Mohamad: Nie, tylko ASCII, chociaż obsługa UTF-8 jest coraz lepsza.
Dietrich Epp
@Dietrich Epp, dziękuję. Myślę, że nie powinno mieć znaczenia, czy adres URL służy do dekoracji i celów SEO, na przykład: www.mysite.com/[postId]/post-title-with-ç-and-õ
Mohamad
1
@Mohamad: Ostatnia część zostanie zmieniona pod maską na post-title-with-%C3%A7-and-%C3%B5, ale nadal będzie wyświetlana na pasku lokalizacji użytkownika jako post-title-with-ç-and-õ.
Dietrich Epp
7
Twoi czytelnicy są Portugalczykami, więc używaj portugalskich znaków.
Dietrich Epp
107

Istnieją dwa zestawy znaków, na które musisz uważać: zarezerwowane i niebezpieczne .

W zastrzeżonych znaków są:

  • ampersand („&”)
  • dolar („$”)
  • znak plus („+”)
  • przecinek („,”)
  • ukośnik ("/")
  • dwukropek (":")
  • średnik (";")
  • równa się („=”)
  • znak zapytania ("?")
  • Symbol „At” („@”)
  • funt ("#").

Znaki ogólnie uważane za niebezpieczne to:

  • przestrzeń (" ")
  • mniejszy i większy niż ("<>")
  • otwórz i zamknij nawiasy („[]”)
  • otwórz i zamknij nawiasy klamrowe („{}”)
  • rura ("|")
  • ukośnik wsteczny ("\")
  • daszek („^”)
  • procent („%”)

Mogłem zapomnieć o jednym lub więcej, co prowadzi do tego, że powtarzam odpowiedź Carla V. Na dłuższą metę prawdopodobnie lepiej będzie, jeśli użyjesz "białej listy" dozwolonych znaków, a następnie zakodujesz łańcuch, zamiast próbować być na bieżąco ze znakami, które są zabronione przez serwery i systemy.

Gary.Ray
źródło
#to zastrzeżony znak używany do zakładek na określonej stronie, utworzony przez posiadanie jednego elementu HTML z pasującym atrybutem nazwy lub atrybutu identyfikatora (sans #-symbol).
TheLonelyGhost
Dzięki - zaktualizowałem odpowiedź.
Gary.Ray,
Znak zapytania pojawia się tutaj zarówno jako zarezerwowany, jak i niebezpieczny - myślę o tym jako o zastrzeżonym, ale mogę się mylić
Jonathan Basile
6
Inni wydają się nie zgadzać, że tylda ~jest niebezpieczna. Czy na pewno tak jest?
drs
3
Biała lista nie jest tak dobra, jeśli obsługuje języki inne niż angielski. Unicode ma po prostu zbyt wiele punktów kodowych OK. Dlatego umieszczenie niebezpiecznych na czarnej liście prawdopodobnie będzie najłatwiejsze do zaimplementowania w wyrażeniach regularnych.
Patanjali
41

Najlepiej jest zachować tylko niektóre znaki (biała lista), zamiast usuwać niektóre znaki (czarna lista).

Możesz technicznie zezwolić na dowolny znak, o ile poprawnie go zakodujesz. Ale aby odpowiedzieć w duchu pytania, powinieneś pozwolić tylko tym postaciom:

  1. Małe litery (zamień duże na małe)
  2. Liczby od 0 do 9
  3. Myślnik - lub podkreślenie _
  4. Tilde ~

Wszystko inne ma potencjalnie specjalne znaczenie. Na przykład możesz pomyśleć, że możesz użyć +, ale można go zastąpić spacją. i jest również niebezpieczny, zwłaszcza jeśli używasz pewnych reguł przepisywania.

Podobnie jak w przypadku innych komentarzy, zapoznaj się ze standardami i specyfikacjami, aby uzyskać szczegółowe informacje.

Carl
źródło
15
Odkryłem dzisiaj, że przed okresem jest zły wybór znaku dla bezpiecznego kodera Base64, ponieważ będą takie rzadkie przypadki, w których zakodowane dane mogą generować dwie kolejne kropki („…”), co jest istotne w że odnosi się do katalogu nadrzędnego.
pohl
5
@pohl: jest to problem tylko wtedy, gdy twój adres URL jest używany jako ścieżka do pliku, albo w kodzie, albo jeśli twój serwer sieciowy faktycznie próbuje zamapować adres URL na pliki przed przekazaniem żądania do skryptu (niestety bardzo powszechne).
André Caron
4
Właściwie, w naszym przypadku użycie go jako ścieżki do pliku byłoby w porządku, ponieważ w unixach pliki mogą mieć wiele, a nawet następujące po sobie kropki w nazwie. Dla nas problem pojawił się w narzędziu monitorującym o nazwie Site Scope, które zawiera błąd (być może naiwne wyrażenie regularne) i zgłaszało fałszywe fałszywe przestoje. Dla nas utknęliśmy w starej wersji zakresu witryny, zespół administracyjny odmawia zapłaty za aktualizację, a jeden bardzo ważny klient ma zapisany w umowie zakres witryny (nie jego odpowiednik). Trzeba przyznać, że większość nie znajdzie się w moich butach.
pohl
8
Dzięki Bogu, że ktoś opublikował listę bez gadania. Jeśli chodzi o kropkę (.) - jak powiedział @pohl, nie używaj jej! Oto kolejny dziwny przypadek w usługach IIS (nie wiem, czy dzieje się tak na innych serwerach internetowych): jeśli znajduje się na końcu adresu URL, najprawdopodobniej zostanie wyświetlony błąd 404 (spróbuje wyszukać [/ nazwa strony] . strona)
nikib3ro
34

Zawsze bezpieczne

Są one bezpieczne (w teorii / specyfikacji), w zasadzie wszędzie z wyjątkiem nazwy domeny.
Kodowanie procentowe wszystkiego, czego nie ma na liście, i gotowe.

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

Czasami bezpieczne

Bezpieczny tylko wtedy, gdy jest używany w określonych składnikach adresu URL; używać ostrożnie.

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

Nigdy nie było bezpiecznie

Zgodnie ze specyfikacją URI (RFC 3986) wszystkie inne znaki muszą być zakodowane w procentach. To zawiera:

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

Jeśli problemem jest maksymalna kompatybilność, ogranicz zestaw znaków do AZ az 0-9 - _.
(z kropkami tylko dla rozszerzeń plików).

Miej na uwadze kontekst

Nawet jeśli jest prawidłowy zgodnie ze specyfikacją, adres URL może nadal być „niebezpieczny”, w zależności od kontekstu. Na przykład plik: /// URL zawierający nieprawidłowe znaki w nazwie pliku lub składnik zapytania zawierający „?”, „=” I „&”, gdy nie są używane jako separatory. Prawidłowa obsługa takich przypadków zależy na ogół od skryptów i można je obejść, ale należy o tym pamiętać.

Beejor
źródło
Czy możesz podać źródła swojego drugiego wniosku („Czasami bezpieczne”)? W szczególności uważam, że mylisz się, mówiąc, że =nie jest to bezpieczne w przypadku zapytań. Na przykład język FIQL akceptuje znaki równości i określa się jako „przyjazny dla URI” oraz „zoptymalizowany i przeznaczony do użycia w komponencie zapytania”. W mojej interpretacji RFC 3986 wyraźnie zezwala na „=”, „&”, „+” i inne w zapytaniach.
DanielM
@DanielM „?”, „=” I „&” są poprawne w zapytaniach według specyfikacji, chociaż w praktyce są szeroko używane do analizowania par nazwa-wartość w zapytaniu. Dlatego mogą być niebezpieczne jako część samych nazw / wartości. To, czy jest to „niebezpieczne”, może być kwestią opinii.
Beejor
Niektóre źródła na żądanie. (1) RFC 3986, rozdział 3.4: „[...] komponenty zapytania są często używane do przenoszenia informacji identyfikujących w postaci par„ klucz = wartość ”[...]” (2) Specyfikacja adresu URL WhatWG, rozdz. 6.2: "Konstruowanie i definiowanie obiektu URLSearchParams jest dość proste: [...] params.toString() // "key=730d67"" (3) Podręcznik PHP, http-build-query: "Generowanie ciągu zapytania zakodowanego w adresie URL. [...] Powyższy przykład zwróci: 0=foo&1=bar[...](4) J. Starr, Perishable Press: „Podczas tworzenia stron internetowych często konieczne jest dodawanie linków, które wymagają sparametryzowanych ciągów zapytań”.
Beejor
@Beejor: Konstruuję adres URL i używam „-” i „;” podczas budowy. To nie jest aplikacja internetowa, ale aplikacja mobilna. Nie jestem programistą stron internetowych, a zatem czy będę bezpieczny, jeśli użyję powyższych dwóch znaków we właściwości Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen To są prawidłowe znaki adresu URL. Chociaż jeśli jest używany do odwoływania się do ścieżek w lokalnym systemie plików, należy pamiętać, że niektóre systemy nie zezwalają na pewne znaki w nazwach plików. Na przykład „plik: /// ścieżka / do / mój: plik.ext” byłby nieprawidłowy na Macu.
Beejor
17

Patrząc na RFC3986 - Uniform Resource Identifier (URI): Generic Syntax , twoje pytanie obraca się wokół składnika ścieżki w identyfikatorze URI.

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

Cytując sekcję 3.3, prawidłowe znaki identyfikatora URI segmentsą typu pchar:

pchar = unreserved / pct-encoded / sub-delims / ":" / "@"

Który rozkłada się na:

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

pct-encoded

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

":" / "@"

Albo innymi słowy: można użyć dowolnego (non-temat kontroli) znak z tabeli ASCII , except / , ?, #, [i ].

To zrozumienie jest poparte przez RFC1738 - Uniform Resource Locators (URL) .

Philzen
źródło
2
To świetny przykład teoretycznie poprawnej odpowiedzi, która prowadzi do problemów, gdy zastosujemy ją do prawdziwego świata, w którym faktycznie żyjemy. Prawdą jest, że większość z tych postaci nie będzie sprawiać problemów przez większość czasu. Ale w prawdziwym świecie istnieją takie rzeczy, jak serwery proxy, routery, bramki, przekaźniki itp., Z których wszystkie „uwielbiają” sprawdzać adresy URL i wchodzić z nimi w interakcję w sposób, który nie uwzględnia teoretycznego standardu. Aby uniknąć tych pułapek, jesteś prawie ograniczony do ucieczki od wszystkiego z wyjątkiem znaków alfanumerycznych, myślnika, podkreślenia i kropki.
deltamind106
1
@ deltamind106 Czy możesz podać przykłady i / lub odniesienia, aby wyjaśnić, które z tych znaków, które są bezpieczne zgodnie ze specyfikacjami RFC, w rzeczywistości nie są? W mojej odpowiedzi wolałbym trzymać się faktów popartych standardami i z przyjemnością zaktualizuję moją odpowiedź, jeśli możesz wskazać fakty, które mogłem pominąć.
Philzen
2
@ deltamind106 Sugeruję raczej, abyśmy starali się, aby produkty były zgodne ze standardami, zamiast mówić programistom, aby tego nie robili. Uważam, że Twoje ostrzeżenie jest zasługujące, ale w razie potrzeby powinniśmy dołożyć starań, aby zgłaszać dostawcom niezgodności.
Lo-Tan
@Philzen: Tworzę adres URL i używam „-” i „;” podczas budowy. To nie jest aplikacja internetowa, ale aplikacja mobilna. Nie jestem programistą stron internetowych, a zatem czy będę bezpieczny, jeśli użyję powyższych dwóch znaków we właściwości Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen Tak, oczywiście -i ;są bezpieczne, oto moja odpowiedź i jasno stwierdza RFC.
Philzen
12

unreserved = ALFA / DIGIT / "-" / "." / „_” / „~”

LKK
źródło
3
Czy „ALPHA” nie oznacza „CYFRA”? Zakładam, że ALPHA to skrót od „alfanumeryczny”, a alfanumeryczny oznacza wielkie, małe litery i cyfry.
Luc
11
W rzeczywistości alfa nie oznacza alfanumerycznego. Alfa i numeryczne to dwie różne rzeczy, a alfanumeryczne to połączenie tych rzeczy. Mógłby tak zapisać swoją odpowiedź: ALFANUMERYCZNY / "-" / "." / "_" / "~"
MacroMan,
1
Notacja ABNF oznaczająca „niezarezerwowane” w dokumencie RFC 3986 wymienia je oddzielnie.
Patanjali
11

Z kontekstu, który opisujesz, podejrzewam, że to, co faktycznie próbujesz stworzyć, to coś, co nazywa się „ślimakiem SEO”. Najlepszą ogólnie znaną praktyką w tym zakresie jest:

  1. Konwertuj na małe litery
  2. Konwertuj całe sekwencje znaków innych niż az i 0-9 na jeden łącznik (-) (bez podkreślenia)
  3. Usuń „słowa stop” z adresu URL, tj. Słowa, których indeksowanie nie ma znaczenia, takie jak „a”, „an” i „the”; „Stop words” Google dla obszernych list

Na przykład artykuł zatytułowany „Użycie! @% $ * Do przedstawiania przekleństw w komiksach” otrzymałby porcję „użytkowanie-reprezentowanie-przekleństw-komiksów”.

chaos
źródło
Czy naprawdę dobrym podejściem jest usunięcie tych „słów pomijanych” z adresu URL? Czy wyszukiwarki będą karać witrynę z tego powodu?
Paulo,
Powszechnie uważa się, że wyszukiwarki uznają tylko część adresu URL i / lub zmniejszają znaczenie późniejszych części, więc dzięki usuwaniu słów ignorowanych maksymalizujesz liczbę słów kluczowych umieszczonych w adresie URL, które masz szansę w rankingu.
chaos
1
@chaos Czy nadal zaleca usuwania stopword, jeśli wziąć pod uwagę to: seobythesea.com/2008/08/google-stopword-patent Ponadto, można polecić dobrą listę z stopwords? To najlepsza lista, jaką do tej pory znalazłem
link-assistant.com/seo-stop-words.html
@ kape123 To nie wygląda dla mnie na bardzo dobrą listę. „c” i „d” to języki programowania i wiele z tych innych słów również wygląda na znaczące. Prawdopodobnie usunąłbym tylko te podstawowe: a i, is, on, of lub, the, with.
mpen
6

Format identyfikatora URI jest zdefiniowany w dokumencie RFC 3986 . Szczegóły w sekcji 3.3.

joschi
źródło
6

Z punktu widzenia SEO, łączniki są preferowane, a nie podkreślenia. Konwertuj na małe litery, usuń wszystkie apostrofy, a następnie zastąp wszystkie niealfanumeryczne ciągi znaków jednym łącznikiem. Odetnij nadmiar łączników na początku i na końcu.

mpen
źródło
3

Miałem podobny problem, chciałem mieć ładne adresy URL i doszedłem do wniosku, że muszę zezwalać tylko na litery, cyfry, - i _ w adresach URL. W porządku, potem napisałem kilka ładnych wyrażeń regularnych i zdałem sobie sprawę, że rozpoznaje on wszystkie znaki UTF8 nie są literami w .NET i został wkręcony. Wydaje się, że jest to znany problem dotyczący silnika wyrażeń regularnych .NET. Więc dotarłem do tego rozwiązania:

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 "-";
    }
}
Lubomir Toshev
źródło
3
W rzeczywistości wyrażenia regularne .NET obsługują Unicode całkiem dobrze. Musisz używać klas znaków Unicode, np. \ P {L} dla wszystkich liter. Zobacz msdn.microsoft.com/en-us/library/20bw873z.aspx#CategoryOrBlock
TheCycoONE
1

Zauważyłem, że bardzo przydatne jest zakodowanie mojego adresu URL na bezpieczny, gdy zwracałem wartość za pośrednictwem ajax / php do adresu URL, który został następnie ponownie odczytany przez stronę.

Wyjście PHP z koderem url dla znaku specjalnego &

//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);

Mam nadzieję, że ktoś uzna moje małe fragmenty kodu za przydatne! :)

Forum DIY
źródło
0

Myślę, że szukasz czegoś takiego jak „Kodowanie adresu URL” - kodowanie adresu URL w celu „bezpiecznego” używania go w sieci:

Oto odniesienie do tego. Jeśli nie chcesz żadnych znaków specjalnych, po prostu usuń te, które wymagają kodowania adresu URL:

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

Andy White
źródło
-4

Od 3 do 50 znaków. Może zawierać małe litery, cyfry i znaki specjalne - kropkę (.), Myślnik (-), podkreślenie (_) i stawkę (@).

Ramji
źródło
4
Jakieś odniesienie do tego?
dakab