Caracteres seguros para url amigable [cerrado]

168

Necesito crear un sitio web que tenga artículos, y me gustaría hacer URL amigables para él, por ejemplo, la URL de la página con

Título: Prueba de artículo

debe convertirse en: http://www.example.com/articles/article_test.

Por supuesto, necesito eliminar algunos caracteres del título como ?o #, pero no estoy seguro de cuáles eliminar.

¿Alguien puede decirme qué personajes son seguros de mantener?

Paulo
fuente
Había una pregunta similar aquí . Compruébalo, también puedes encontrar algunas respuestas útiles allí (había muchas).
Rook

Respuestas:

210

Para citar la sección 2.3 de RFC 3986 :

"Los caracteres que están permitidos en un URI pero que no tienen un propósito reservado se denominan sin reserva. Estos incluyen letras mayúsculas y minúsculas, dígitos decimales, guiones, puntos, guiones bajos y tilde".

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

Tenga en cuenta que RFC 3986 enumera menos signos de puntuación reservados que el RFC 2396 anterior .

Saltar cabeza
fuente
@Skip Head, ¿los "caracteres" incluyen caracteres latinos codificados como çy õ?
Mohamad
66
@Mohamad: No, solo ASCII, aunque el soporte UTF-8 está mejorando.
Dietrich Epp
@Dietrich Epp, gracias. Supongo que no debería importar si la URL es para fines de decoración y SEO, como: www.mysite.com/[postIdfont>/post-title-with-ç-and-õ
Mohamad
1
@Mohamad: La última parte allí se cambiará bajo el capó a post-title-with-%C3%A7-and-%C3%B5, pero aún se mostrará en la barra de ubicación del usuario como post-title-with-ç-and-õ.
Dietrich Epp
77
Sus lectores son portugueses, así que use caracteres portugueses.
Dietrich Epp
107

Hay dos conjuntos de caracteres que debes tener en cuenta: reservados e inseguros .

Los caracteres reservados son:

  • ampersand ("&")
  • dólar ("$")
  • signo más ("+")
  • coma (",")
  • barra inclinada ("/")
  • colon (":")
  • punto y coma (";")
  • es igual a ("=")
  • signo de interrogación ("?")
  • Símbolo 'At' ("@")
  • libra ("#").

Los caracteres generalmente considerados inseguros son:

  • espacio (" ")
  • menor que y mayor que ("<>")
  • abrir y cerrar paréntesis ("[]")
  • abrir y cerrar llaves ("{}")
  • tubería ("|")
  • barra invertida ("\")
  • caret ("^")
  • por ciento ("%")

Puede que haya olvidado uno o más, lo que me lleva a repetir la respuesta de Carl V. A la larga, probablemente sea mejor usar una "lista blanca" de caracteres permitidos y luego codificar la cadena en lugar de tratar de mantenerse al tanto de los caracteres que los servidores y sistemas no permiten.

Gary Ray
fuente
#es un carácter reservado utilizado para marcadores en una página específica, creado al tener un elemento HTML con un atributo de nombre o atributo de identificación (sans #-symbol).
TheLonelyGhost
Gracias. He actualizado la respuesta.
Gary.Ray
El signo de interrogación aparece aquí como reservado e inseguro. Creo que es solo reservado, pero puedo ser incorrecto
Jonathan Basile
66
Otros parecen estar en desacuerdo con que la tilde ~no es segura. ¿Estás seguro de que es?
Dres
3
La lista blanca no es tan buena si se manejan otros idiomas además del inglés. Unicode simplemente tiene demasiados puntos de código OK. Por lo tanto, las listas negras de las inseguras probablemente sean las más fáciles de implementar en expresiones regulares.
Patanjali
41

Es mejor mantener solo algunos caracteres (lista blanca) en lugar de eliminar ciertos caracteres (lista negra).

Técnicamente, puede permitir cualquier carácter, siempre que lo codifique correctamente. Pero, para responder en el espíritu de la pregunta, solo debe permitir estos caracteres:

  1. Letras minúsculas (convertir mayúsculas a minúsculas)
  2. Números, del 0 al 9
  3. Un guión, o guión bajo _
  4. Tilde ~

Todo lo demás tiene un significado potencialmente especial. Por ejemplo, puede pensar que puede usar +, pero se puede reemplazar con un espacio. & también es peligroso, especialmente si se usan algunas reglas de reescritura.

Al igual que con los otros comentarios, consulte los estándares y especificaciones para obtener detalles completos.

carl
fuente
15
Un preiodo, descubrí hoy, es una mala elección de caracteres para usar para un codificador Base64 seguro para URL, porque habrá esos casos raros en los que sus datos codificados pueden producir dos puntos consecutivos (".."), lo cual es significativo en que se refiere al directorio padre.
pohl
55
@pohl: eso solo es un problema si su URL se usa como ruta de archivo, ya sea en su código o si su servidor web realmente trata de asignar la URL a los archivos antes de reenviar la solicitud a un script (desafortunadamente muy común).
André Caron
44
En realidad, en nuestro caso usarlo como una ruta de archivo estaría bien, ya que en archivos Unix se les permite tener puntos múltiples, e incluso consecutivos, en sus nombres. Para nosotros, el problema surgió en una herramienta de monitoreo llamada Site Scope que tiene un error (tal vez una expresión regular ingenua) e informaba falsos falsos tiempos de inactividad. Para nosotros, estamos atascados en una versión anterior de Site Scope, el equipo de administración se niega a pagar una actualización, y un cliente muy importante tiene Site Scope (no un equivalente) escrito en su contrato. Es cierto que la mayoría no se encontrará en mis zapatos.
Pohl
8
Gracias a Dios que alguien publicó una lista sin mucho parloteo. En cuanto al punto (.) - como dijo @pohl, ¡no lo use! Aquí hay otro caso extraño en IIS (no sé si esto sucede en otros servidores web): si está al final de su URL, lo más probable es que obtenga un error 404 (intentará buscar [/ pagename]
.página
34

Siempre seguro

Estos son seguros (en teoría / especificaciones), básicamente en cualquier lugar excepto el nombre de dominio.
Codifique por ciento cualquier cosa que no esté en la lista, y ya está listo.

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

A veces seguro

Solo seguro cuando se usa dentro de componentes URL específicos; usar con cuidado.

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

Nunca seguro

De acuerdo con la especificación URI (RFC 3986), todos los demás caracteres deben estar codificados en porcentaje. Esto incluye:

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

Si le preocupa la compatibilidad máxima, limite el juego de caracteres a AZ az 0-9 - _.
(con puntos solo para extensiones de nombre de archivo).

Mantenga el contexto en mente

Incluso si es válido por especificación, una URL puede ser "insegura", según el contexto. Como un archivo: /// URL que contiene caracteres de nombre de archivo no válidos, o un componente de consulta que contiene "?", "=" Y "&" cuando no se utilizan como delimitadores. El manejo correcto de estos casos generalmente depende de sus scripts y se puede solucionar, pero es algo a tener en cuenta.

Beejor
fuente
¿Podría proporcionar alguna fuente para su segundo reclamo ("A veces seguro")? En particular, creo que está equivocado al decir que =no es seguro para consultas. Por ejemplo, FIQL acepta signos de igualdad y se describe a sí mismo como "compatible con URI" y "optimizado y destinado para su uso en el componente de consulta". En mi interpretación, RFC 3986 permite explícitamente "=", "&", "+" y otros en las consultas.
DanielM
@DanielM "?", "=" Y "&" son válidos en consultas por especificación, aunque en la práctica son ampliamente utilizados para analizar pares de nombre-valor dentro de la consulta. Por lo tanto, pueden ser inseguros como parte de los propios nombres / valores. Si esto constituye o no "inseguro" puede ser una cuestión de opinión.
Beejor
Algunas fuentes, según lo solicitado. (1) RFC 3986, Sección 3.4: "los componentes de [...] consulta se usan a menudo para llevar información de identificación en forma de pares 'clave = valor' [...]" (2) WhatWG URL Spec, Sec. 6.2: "Construir y encadenar un objeto URLSearchParams es bastante sencillo: [...] params.toString() // "key=730d67"" (3) PHP Manual, http-build-query: "Generar una cadena de consulta codificada en URL. [...] El ejemplo anterior generará: 0=foo&1=bar[...]"(4) J. Starr, Perishable Press:" Al crear páginas web, a menudo es necesario agregar enlaces que requieren cadenas de consulta parametrizadas ".
Beejor
@Beejor: estoy construyendo una URL y uso '-' y ';' durante la construcción. No es una aplicación web sino una aplicación móvil. No soy un desarrollador web y, por lo tanto, ¿estaría seguro si uso los dos caracteres anteriores en la propiedad Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen Esos son caracteres de URL válidos. Aunque si se usa para hacer referencia a rutas en un sistema de archivos local, tenga en cuenta que algunos sistemas no permiten ciertos caracteres en los nombres de archivo. Por ejemplo, "file: /// path / to / my: file.ext" no sería válido en Mac.
Beejor
17

En cuanto a RFC3986 - Identificador uniforme de recursos (URI): sintaxis genérica , su pregunta gira en torno al componente de ruta de un URI.

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

Citando la sección 3.3, los caracteres válidos para un URI segmentson de tipo pchar:

pchar = sin reservas / codificado por pct / subdelimitaciones / ":" / "@"

Que se descompone en:

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

pct-encoded

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

":" / "@"

O en otras palabras: Usted puede utilizar cualquier carácter (no control-) de la tabla ASCII , excepto / , ?, #, [y ].

Este entendimiento está respaldado por RFC1738 - Localizadores uniformes de recursos (URL) .

Philzen
fuente
2
Este es un gran ejemplo de una respuesta teóricamente correcta, que genera problemas cuando se aplica al mundo real en el que realmente vivimos. Es cierto que la mayoría de esos personajes no causarán problemas la mayor parte del tiempo. Pero existen en el mundo real cosas como servidores proxy, enrutadores, puertas de enlace, retransmisiones, etc., todo lo cual "ama" inspeccionar e interactuar con las URL de formas que no respetan el estándar teórico. Para evitar estas trampas, estás bastante limitado a escapar de todo, excepto los alfanuméricos, el guión, el guión bajo y el punto.
deltamind106
1
@ deltamind106 ¿Puede proporcionar ejemplos y / o referencias para aclarar cuáles de esos caracteres son seguros de acuerdo con los RFC? Prefiero apegarme a los hechos respaldados por los estándares en mi respuesta, y me complace actualizar mi respuesta si puede identificar cualquier hecho que haya descuidado.
Philzen
2
@ deltamind106 Sugeriría que intentemos que los productos sigan los estándares en lugar de decirle a los desarrolladores que no lo hagan. Considero que su advertencia es meritoria, pero deberíamos hacer nuestra parte en informar el incumplimiento a los proveedores si es necesario.
Lo-Tan
@ Philzen: Estoy construyendo una URL y uso '-' y ';' durante la construcción. No es una aplicación web sino una aplicación móvil. No soy un desarrollador web y, por lo tanto, ¿estaría seguro si uso los dos caracteres anteriores en la propiedad Path? docs.microsoft.com/en-us/dotnet/api/…
karsnen
1
@karsnen Sí, por supuesto, -y ;están a salvo, eso es lo que mi respuesta y RFC establecen claramente.
Philzen
12

sin reservas = ALFA / DÍGITO / "-" / "." / "_" / "~"

LKK
fuente
3
¿"ALFA" no implica "DÍGITO"? Supongo que ALPHA es la abreviatura de "alfanumérico", y alfanumérico significa mayúsculas, minúsculas y dígitos.
Luc
11
En realidad, alfa no implica alfanumérico. Alfa y numérico son 2 cosas distintas y alfanumérico es la combinación de esas cosas. Podría haber escrito su respuesta así: ALFANUMÉRICO / "-" / "." / "_" / "~"
MacroMan
1
La notación ABNF para 'no reservado' en RFC 3986 los enumera por separado.
Patanjali
11

Por el contexto que describe, sospecho que lo que realmente está tratando de hacer es algo llamado 'babosa SEO'. La mejor práctica general conocida para aquellos es:

  1. Convertir a minúsculas
  2. Convierta secuencias enteras de caracteres que no sean az y 0-9 en un guión (-) (no guiones bajos)
  3. Elimine 'detener palabras' de la URL, es decir, palabras no indexables de manera significativa como 'a', 'an' y 'the'; Google 'palabras de detención' para listas extensas

Entonces, como ejemplo, un artículo titulado "The Usage of! @% $ * To Represent Swearing In Comics" obtendría una babosa de "use-represent-swearing-comics".

caos
fuente
¿Es realmente un buen enfoque eliminar estas "palabras vacías" de la URL? ¿Los motores de búsqueda penalizarían un sitio web debido a esto?
Paulo
Por lo general, se cree que los motores de búsqueda solo reconocen una parte de la URL y / o otorgan una importancia reducida a las partes posteriores, por lo que al eliminar las palabras de detención, lo que está haciendo es maximizar el número de palabras clave que incrusta en su URL para que tenga la oportunidad de clasificación en realidad.
caos
1
@chaos ¿Sigue recomendando eliminar StopWord si tiene en cuenta esto: seobythesea.com/2008/08/google-stopword-patent Además, ¿puede recomendar una buena lista de palabras vacías? Esta es la mejor lista que he encontrado hasta ahora - link-assistant.com/seo-stop-words.html
nikib3ro
@ kape123 Eso no me parece una lista muy buena. "c" y "d" son lenguajes de programación, y muchas de esas otras palabras también parecen significativas. Probablemente me quede solo con los básicos: a, y, is, on, of, o, the, with.
mpen
6

El formato para un URI se define en RFC 3986 . Consulte la sección 3.3 para más detalles.

joschi
fuente
6

Desde una perspectiva de SEO, los guiones son preferibles a los guiones bajos. Convierta a minúsculas, elimine todos los apóstrofes, luego reemplace todas las cadenas de caracteres no alfanuméricas con un solo guión. Recorte el exceso de guiones desde el principio y el final

mpen
fuente
3

Tuve un problema similar, quería tener urls bonitas y llegué a la conclusión de que solo tenía que permitir letras, dígitos, y _ en urls. Eso está bien, luego escribí algunas expresiones agradables y me di cuenta de que reconoce que todos los caracteres UTF8 no son letras en .NET y se atornilló. Esto parece ser un problema conocido para .NET regex engine. Entonces llegué a esta solución:

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
fuente
3
Las expresiones regulares .NET admiten bastante bien unicode. Debe utilizar clases de caracteres unicode, por ejemplo, \ p {L} para todas las letras. Ver msdn.microsoft.com/en-us/library/20bw873z.aspx#CategoryOrBlock
TheCycoONE
1

Me pareció muy útil codificar mi url en una segura cuando estaba devolviendo un valor a través de ajax / php a una url que luego fue leída por la página nuevamente.

Salida PHP con codificador url para el carácter especial &

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

¡Espero que alguien encuentre útil mis pequeños extractos de código! :)

DIY-Forum
fuente
0

Creo que está buscando algo como "Codificación de URL": codificar una URL para que sea "seguro" usarlo en la web:

Aquí hay una referencia para eso. Si no desea caracteres especiales, simplemente elimine los que requieran codificación URL:

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

Andy White
fuente
-4

Entre 3-50 personajes. Puede contener letras minúsculas, números y caracteres especiales: punto (.), Guión (-), guión bajo (_) y a la velocidad (@).

Ramji
fuente
44
¿Alguna referencia para eso?
dakab