Caractères sûrs pour une URL conviviale [fermé]

168

J'ai besoin de créer un site Web qui contiendra des articles, et j'aimerais lui créer des URL conviviales, par exemple l'URL de la page avec

Titre: Article Test

devrait devenir: http://www.example.com/articles/article_test.

Bien sûr, je dois supprimer certains caractères du titre comme ?ou #, mais je ne suis pas sûr de ceux à supprimer.

Quelqu'un peut-il me dire quels personnages peuvent être conservés en toute sécurité?

Paulo
la source
Il y avait une question similaire, ici . Jetez-y un œil, vous y trouverez peut-être des réponses utiles (il y en avait pas mal).
Rook

Réponses:

210

Pour citer la section 2.3 de la RFC 3986 :

"Les caractères autorisés dans un URI mais n'ayant pas de fonction réservée sont appelés non réservés. Il s'agit notamment des lettres majuscules et minuscules, des chiffres décimaux, des tirets, des points, des traits de soulignement et du tilde."

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

Notez que la RFC 3986 répertorie moins de signes de ponctuation réservés que l'ancienne RFC 2396 .

Passer la tête
la source
@Skip Head, est-ce que "caractères" inclut des caractères encodés en latin comme çet õ?
Mohamad
6
@Mohamad: Non, ASCII uniquement, bien que le support UTF-8 s'améliore.
Dietrich Epp
@Dietrich Epp, merci. Je suppose que cela ne devrait pas avoir d'importance si l'URL est à des fins de décoration et de référencement, comme: www.monsite.com/[postId <
Mohamad
1
@Mohamad: La dernière partie sera modifiée sous le capot en post-title-with-%C3%A7-and-%C3%B5, mais elle s'affichera toujours dans la barre de localisation de l'utilisateur sous la forme post-title-with-ç-and-õ.
Dietrich Epp
7
Vos lecteurs sont portugais, utilisez donc des caractères portugais.
Dietrich Epp
107

Il y a deux ensembles de caractères auxquels vous devez faire attention: réservé et dangereux .

Les caractères réservés sont:

  • esperluette ("&")
  • dollar ("$")
  • signe plus ("+")
  • virgule (",")
  • barre oblique ("/")
  • deux points (":")
  • point-virgule (";")
  • égale ("=")
  • point d'interrogation ("?")
  • Symbole "At" ("@")
  • livre ("#").

Les caractères généralement considérés comme dangereux sont:

  • espace (" ")
  • inférieur et supérieur à ("<>")
  • ouvrir et fermer les crochets ("[]")
  • accolades ouvertes et fermées ("{}")
  • tuyau ("|")
  • barre oblique inverse ("\")
  • caret ("^")
  • pourcentage ("%")

J'en ai peut-être oublié un ou plusieurs, ce qui m'amène à faire écho à la réponse de Carl V. À long terme, vous feriez probablement mieux d'utiliser une «liste blanche» de caractères autorisés, puis d'encoder la chaîne plutôt que d'essayer de vous tenir au courant des caractères qui ne sont pas autorisés par les serveurs et les systèmes.

Gary Ray
la source
#est un caractère réservé utilisé pour les signets sur une page spécifique, créé en ayant un élément HTML avec un attribut de nom ou d'id correspondant (sans #-symbole).
TheLonelyGhost
Merci - J'ai mis à jour la réponse.
Gary Ray
Le point d'interrogation apparaît ici à la fois comme réservé et dangereux - je le considère comme uniquement réservé, mais je me trompe peut-être
Jonathan Basile
6
D'autres semblent ne pas être d'accord sur le fait que le tilde ~est dangereux. Etes-vous sûr que oui?
drs
3
La liste blanche n'est pas très bonne si vous utilisez des langues autres que l'anglais. Unicode a juste trop de points de code OK. Par conséquent, la mise sur liste noire des éléments non sécurisés est probablement la plus simple à implémenter dans les expressions régulières.
Patanjali
41

Il est préférable de ne conserver que certains caractères (liste blanche) au lieu de supprimer certains caractères (liste noire).

Vous pouvez techniquement autoriser n'importe quel caractère, à condition de l'encoder correctement. Mais, pour répondre dans l'esprit de la question, vous ne devez autoriser que ces caractères:

  1. Lettres minuscules (convertir les majuscules en minuscules)
  2. Nombres, de 0 à 9
  3. Un tiret - ou un trait de soulignement _
  4. Tilde ~

Tout le reste a une signification potentiellement spéciale. Par exemple, vous pouvez penser que vous pouvez utiliser +, mais il peut être remplacé par un espace. & est également dangereux, surtout si vous utilisez certaines règles de réécriture.

Comme pour les autres commentaires, consultez les normes et spécifications pour plus de détails.

Carl
la source
15
Une pré-période, que j'ai découverte aujourd'hui, est un mauvais choix de caractère à utiliser pour un encodeur Base64 sécurisé pour les URL, car il y aura ces rares cas où vos données encodées peuvent produire deux points consécutifs (".."), ce qui est significatif dans qu'il fait référence au répertoire parent.
pohl
5
@pohl: ce n'est un problème que si votre URL est utilisée comme chemin de fichier, soit dans votre code, soit si votre serveur Web essaie réellement de mapper l'URL sur des fichiers avant de transférer la requête vers un script (malheureusement très courant).
André Caron
4
En fait, dans notre cas, l'utiliser comme chemin de fichier serait acceptable, car sous Unix, les fichiers sont autorisés à avoir plusieurs points, voire consécutifs, dans leurs noms. Pour nous, le problème est survenu dans un outil de surveillance appelé Site Scope qui a un bogue (peut-être un regex naïf) et il signalait de faux temps d'arrêt. Pour nous, nous sommes bloqués sur une ancienne version de Site Scope, l'équipe d'administration refuse de payer pour une mise à niveau, et un client très important a le Site Scope (pas un équivalent) inscrit dans son contrat. Certes, la plupart ne se retrouveront pas à ma place.
pohl
8
Dieu merci que quelqu'un ait posté une liste sans trop de bavardages. Quant au point (.) - comme @pohl l'a dit, ne l'utilisez pas! Voici un autre cas étrange sur IIS (je ne sais pas si cela se produit sur d'autres serveurs Web): s'il se trouve à la fin de votre URL, vous obtiendrez probablement une erreur 404 (il essaiera de rechercher [/ pagename] . page)
nikib3ro
34

Toujours sûr

Ceux-ci sont sûrs (en théorie / spécification), essentiellement n'importe où sauf le nom de domaine.
Encodez en pourcentage tout ce qui n'est pas répertorié, et vous êtes prêt à partir.

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

Parfois sûr

Uniquement sûr lorsqu'il est utilisé dans des composants URL spécifiques; utiliser avec précaution.

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

Jamais sûr

Selon la spécification URI (RFC 3986), tous les autres caractères doivent être encodés en pourcentage. Ceci comprend:

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

Si la compatibilité maximale est un problème, limitez le jeu de caractères à AZ az 0-9 - _.
(avec des points uniquement pour les extensions de nom de fichier).

Gardez le contexte à l'esprit

Même si elle est valide selon les spécifications, une URL peut toujours être "non sécurisée", selon le contexte. Comme une URL file: /// contenant des caractères de nom de fichier non valides, ou un composant de requête contenant "?", "=" Et "&" lorsqu'il n'est pas utilisé comme délimiteur. La gestion correcte de ces cas dépend généralement de vos scripts et peut être contournée, mais c'est quelque chose à garder à l'esprit.

Beejor
la source
Pourriez-vous fournir des sources pour votre deuxième réclamation («Parfois sûr»)? En particulier, je pense que vous avez tort de dire que ce =n'est pas sûr pour les requêtes. Par exemple, FIQL accepte les signes égaux et se décrit comme étant "compatible URI" et "optimisé et destiné à être utilisé dans le composant de requête". Dans mon interprétation, la RFC 3986 autorise explicitement "=", "&", "+" et autres dans les requêtes.
DanielM du
@DanielM "?", "=" Et "&" sont valides dans les requêtes par spécification, bien qu'en pratique ils soient largement utilisés pour analyser les paires nom-valeur dans la requête. Ainsi, ils peuvent être dangereux dans le cadre des noms / valeurs eux-mêmes. La question de savoir si cela constitue ou non «dangereux» peut être une question d’opinion.
Beejor
Certaines sources, comme demandé. (1) RFC 3986, Sec 3.4: «[...] les composants de requête sont souvent utilisés pour transporter des informations d'identification sous la forme de paires« clé = valeur »[...]» (2) WhatWG URL Spec, Sec. 6.2: "Construire et stringifier un objet URLSearchParams est assez simple: [...] params.toString() // "key=730d67"" (3) Manuel PHP, http-build-query: "Génère une chaîne de requête encodée en URL. [...] L'exemple ci-dessus va afficher: 0=foo&1=bar[...]"(4) J. Starr, Perishable Press:" Lors de la création de pages Web, il est souvent nécessaire d'ajouter des liens qui nécessitent des chaînes de requête paramétrées. "
Beejor
@Beejor: Je construis une URL et j'utilise '-' et ';' pendant la construction. Ce n'est pas une application Web mais une application mobile. Pas un développeur Web et par conséquent, serais-je en sécurité si j'utilise les deux caractères ci-dessus dans la propriété Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen le
1
@karsnen Ce sont des caractères d'URL valides. Cependant, s'il est utilisé pour référencer des chemins sur un système de fichiers local, gardez à l'esprit que certains systèmes interdisent certains caractères dans les noms de fichiers. Par exemple, "file: /// chemin / vers / mon: fichier.ext" serait invalide sur Mac.
Beejor le
17

En regardant RFC3986 - Uniform Resource Identifier (URI): Generic Syntax , votre question tourne autour du composant de chemin d'un URI.

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

Citant la section 3.3, les caractères valides pour un URI segmentsont de type pchar:

pchar = non réservé / pct-encoded / sub-delims / ":" / "@"

Ce qui se décompose en:

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

pct-encoded

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

":" / "@"

En d' autres termes: Vous pouvez utiliser un caractère (non-contrôle-) de la table ASCII , excepter / , ?, #, [et ].

Cette compréhension est soutenue par RFC1738 - Uniform Resource Locators (URL) .

Philzen
la source
2
Ceci est un excellent exemple d'une réponse théoriquement correcte, qui conduit à des problèmes lorsqu'elle est appliquée au monde réel dans lequel nous vivons réellement. Il est vrai que la plupart de ces personnages ne causeront pas de problème la plupart du temps. Mais il existe dans le monde réel des choses comme des proxys, des routeurs, des passerelles, des relais, etc., qui «aiment» tous inspecter et interagir avec les URL d'une manière qui ne respecte pas la norme théorique. Pour éviter ces pièges, vous êtes quasiment limité à tout échapper à l'exception des alphanumériques, des tirets, des traits de soulignement et des points.
deltamind106
1
@ deltamind106 Pouvez-vous fournir des exemples et / ou des références pour clarifier lesquels de ces caractères sûrs selon les RFC ne le sont pas? Je préférerais m'en tenir aux faits étayés par des normes dans ma réponse, et je suis heureux de mettre à jour ma réponse si vous pouvez identifier des faits que j'ai peut-être négligés.
Philzen
2
@ deltamind106 Je suggère que nous essayions de faire en sorte que les produits respectent les normes plutôt que de dire aux développeurs de ne pas le faire. Je considère que votre mise en garde est justifiée, mais nous devons faire notre part en signalant la non-conformité aux fournisseurs si nécessaire.
Lo-Tan
@Philzen: Je construis une URL et j'utilise '-' et ';' pendant la construction. Ce n'est pas une application Web mais une application mobile. Pas un développeur Web et par conséquent, serais-je en sécurité si j'utilise les deux caractères ci-dessus dans la propriété Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen le
1
@karsnen Oui bien sûr -et ;sont sûrs, c'est ce que ma réponse et RFC indiquent clairement.
Philzen le
12

non réservé = ALPHA / DIGIT / "-" / "." / "_" / "~"

LKK
la source
3
"ALPHA" n'implique-t-il pas "DIGIT"? Je suppose que ALPHA est l'abréviation de "alphanumérique", et alphanumérique signifie majuscules, minuscules et chiffres.
Luc
11
En fait, alpha n'implique pas alphanumérique. L'alpha et le numérique sont 2 choses distinctes et l'alphanumérique est la combinaison de ces choses. Il aurait pu écrire sa réponse comme ceci: ALPHANUMERIC / "-" / "." / "_" / "~"
MacroMan
1
La notation ABNF pour «sans réserve» dans la RFC 3986 les répertorie séparément.
Patanjali
11

D'après le contexte que vous décrivez, je soupçonne que ce que vous essayez réellement de faire est quelque chose qui s'appelle un «slug SEO». La meilleure pratique générale connue pour ceux-ci est:

  1. Convertir en minuscules
  2. Convertir des séquences entières de caractères autres que az et 0-9 en un trait d'union (-) (pas de traits de soulignement)
  3. Supprimez les «mots vides» de l'URL, c'est-à-dire les mots non indexables comme «a», «an» et «le»; Google "mots vides" pour des listes étendues

Ainsi, à titre d'exemple, un article intitulé "L'utilisation de! @% $ * Pour représenter les jurons dans les bandes dessinées" obtiendrait un slug de "l'utilisation-représentent-jurons-bandes dessinées".

le chaos
la source
Est-ce vraiment une bonne approche de supprimer ces "mots vides" de l'URL? Les moteurs de recherche pénaliseraient-ils un site Web à cause de cela?
Paulo
On pense généralement que les moteurs de recherche ne reconnaissent qu'une partie de l'URL et / ou donnent une signification réduite aux parties ultérieures.Par conséquent, en supprimant les mots vides, vous maximisez le nombre de mots-clés que vous intégrez dans votre URL. de classement réel sur.
chaos
1
@chaos Recommandez-vous toujours de décaper StopWord, si vous tenez compte de ceci: seobythesea.com/2008/08/google-stopword-patent Aussi, pouvez-vous recommander une bonne liste de mots vides? C'est la meilleure liste que j'ai trouvée jusqu'à présent - link-assistant.com/seo-stop-words.html
nikib3ro
@ kape123 Cela ne me semble pas être une très bonne liste. "c" et "d" sont des langages de programmation, et beaucoup de ces autres mots semblent également significatifs. Je supprimerais probablement les éléments de base: a, et, est, sur, de, ou, le, avec.
mpen
6

Le format d'un URI est défini dans la RFC 3986 . Voir la section 3.3 pour plus de détails.

Joschi
la source
6

Du point de vue du référencement, les tirets sont préférés aux traits de soulignement. Convertissez en minuscules, supprimez toutes les apostrophes, puis remplacez toutes les chaînes de caractères non alphanumériques par un seul trait d'union. Coupez les tirets en excès au début et à la fin.

mpen
la source
3

J'ai eu un problème similaire, je voulais avoir de jolies URL et je suis arrivé à la conclusion que je ne dois autoriser que les lettres, les chiffres et _ dans les URL. C'est bien, alors j'ai écrit une belle regex et j'ai réalisé qu'il reconnaît que tous les caractères UTF8 ne sont pas des lettres en .NET et qu'il était vissé. Cela semble être un problème connu pour le moteur .NET regex. Alors je suis arrivé à cette solution:

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
la source
3
Les expressions régulières .NET supportent assez bien l'Unicode en fait. Vous devez utiliser des classes de caractères Unicode, par exemple \ p {L} pour toutes les lettres. Voir msdn.microsoft.com/en-us/library/20bw873z.aspx#CategoryOrBlock
TheCycoONE
1

J'ai trouvé très utile d'encoder mon URL en une URL sûre lorsque je renvoyais une valeur via ajax / php à une URL qui était ensuite lue à nouveau par la page.

Sortie PHP avec encodeur url pour le caractère spécial &

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

J'espère que tout le monde trouvera mes petits extraits de code utiles! :)

DIY-Forum
la source
0

Je pense que vous recherchez quelque chose comme "Encodage d'URL" - encoder une URL pour qu'elle soit "sûre" à utiliser sur le Web:

Voici une référence pour cela. Si vous ne voulez pas de caractères spéciaux, supprimez simplement ceux qui nécessitent un encodage URL:

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

Andy White
la source
-4

Entre 3 et 50 caractères. Peut contenir des lettres minuscules, des chiffres et des caractères spéciaux - point (.), Tiret (-), trait de soulignement (_) et au taux (@).

Ramji
la source
4
Une référence pour ça?
dakab le