2009-05-11 17 views
25

Los valores por defecto de la clase Uri a RFC 2396. Para OpenID y OAuth, necesito Uri escapar coherente con RFC 3986.Como llegar Uri.EscapeDataString para cumplir con el RFC 3986

Desde el System.Uri class documentation:

Por defecto, cualquier carácter reservado en el URI se escapa de acuerdo con RFC 2396. Este comportamiento cambia si se habilitan los identificadores de recursos internacionales o el análisis de nombres de dominio internacional, en cuyo caso se escapan los caracteres reservados en el URI de acuerdo con RFC 3986 y RFC 3987.

La documentación también establece que la activación de este modo de IRI y por lo tanto el comportamiento RFC 3986 significa la adición de un elemento de la sección uri en Machine.config y esto a su aplicación/archivo web.config:

<configuration> 
    <uri> 
    <idn enabled="All" /> 
    <iriParsing enabled="true" /> 
    </uri> 
</configuration> 

Pero si este está presente en el archivo .config o no, obtengo el mismo comportamiento de escape (no 3986) para una aplicación .NET 3.5 SP1. ¿Qué más necesito hacer para obtener Uri.EscapeDataString para usar las reglas RFC 3986? (específicamente, para escapar de los caracteres reservados como se define en esa RFC)

+0

He agregado algo del contenido de la comunidad con respecto al error tipográfico en el ejemplo de sintaxis. –

+0

Presenté esto internamente como un error con .NET Framework (trabajo para MSFT). Lo reconocen como un error de documentación, ya que de hecho esta configuración de configuración * no * hace que la clase Uri se comporte como RFC 3986 con respecto al escape. –

Respuesta

31

Al no haber podido obtener Uri.EscapeDataString para asumir el comportamiento de RFC 3986, escribí mi propio método de escape que cumple con RFC 3986. Aprovecha Uri.EscapeDataString, y luego 'actualiza' el escape para cumplir con RFC 3986.

/// <summary> 
/// The set of characters that are unreserved in RFC 2396 but are NOT unreserved in RFC 3986. 
/// </summary> 
private static readonly string[] UriRfc3986CharsToEscape = new[] { "!", "*", "'", "(", ")" }; 

/// <summary> 
/// Escapes a string according to the URI data string rules given in RFC 3986. 
/// </summary> 
/// <param name="value">The value to escape.</param> 
/// <returns>The escaped value.</returns> 
/// <remarks> 
/// The <see cref="Uri.EscapeDataString"/> method is <i>supposed</i> to take on 
/// RFC 3986 behavior if certain elements are present in a .config file. Even if this 
/// actually worked (which in my experiments it <i>doesn't</i>), we can't rely on every 
/// host actually having this configuration element present. 
/// </remarks> 
internal static string EscapeUriDataStringRfc3986(string value) { 
    // Start with RFC 2396 escaping by calling the .NET method to do the work. 
    // This MAY sometimes exhibit RFC 3986 behavior (according to the documentation). 
    // If it does, the escaping we do that follows it will be a no-op since the 
    // characters we search for to replace can't possibly exist in the string. 
    StringBuilder escaped = new StringBuilder(Uri.EscapeDataString(value)); 

    // Upgrade the escaping to RFC 3986, if necessary. 
    for (int i = 0; i < UriRfc3986CharsToEscape.Length; i++) { 
     escaped.Replace(UriRfc3986CharsToEscape[i], Uri.HexEscape(UriRfc3986CharsToEscape[i][0])); 
    } 

    // Return the fully-RFC3986-escaped string. 
    return escaped.ToString(); 
} 
+2

¿Sabes si .net 4.5 realmente soluciona esto finalmente? http://msdn.microsoft.com/en-us/library/hh367887(v=VS.110).aspx –

+1

No lo creo. –

+2

.NET 4.5 ha solucionado esto. –

0

¿Qué versión de la infraestructura está utilizando? Parece que muchos de estos cambios se realizaron en (from MSDN) ".NET Framework 3.5. 3.0 SP1 y 2.0 SP1".

+1

He agregado que estoy usando .NET 3.5 SP1 a mi pregunta. Observo con cierta diversión que el artículo de MSDN que enlazas también es groseramente incoherente, teniendo XML no válido, Uri y uri intercambiables cuando la mayúscula es importante, y cuando se supone que el valor es "todo" de "verdadero", como lo demuestra el documento en sí más tarde. :) –

-1

no pude encontrar una mejor respuesta (ya sea marco del 100% o 100% reimplementación), por lo que he creado esta abominación. Parece estar trabajando con OAuth.

class al_RFC3986 
{ 
    public static string Encode(string s) 
    { 
     StringBuilder sb = new StringBuilder(s.Length*2);//VERY rough estimate 
     byte[] arr = Encoding.UTF8.GetBytes(s); 

     for (int i = 0; i < arr.Length; i++) 
     { 
      byte c = arr[i]; 

      if(c >= 0x41 && c <=0x5A)//alpha 
       sb.Append((char)c); 
      else if(c >= 0x61 && c <=0x7A)//ALPHA 
       sb.Append((char)c); 
      else if(c >= 0x30 && c <=0x39)//123456789 
       sb.Append((char)c); 
      else if (c == '-' || c == '.' || c == '_' || c == '~') 
       sb.Append((char)c); 
      else 
      { 
       sb.Append('%'); 
       sb.Append(Convert.ToString(c, 16).ToUpper()); 
      } 
     } 
     return sb.ToString(); 
    } 
} 
+0

Motivo de los votos a favor –

+0

Porque la respuesta es de mal gusto imo. – Anders

3

En realidad, esto se ha solucionado en .NET 4.5 para trabajar de manera predeterminada, consulte here.

acabo de crear una nueva biblioteca llamada PUrify (después de funcionar en este tema) que se encargará de conseguir que esto funcione para .NET pre 4,5 (trabaja para 3.5) y Mono través de una variación del enfoque en este post. PUrify no cambia EscapeDataString pero le permite tener Uris con caracteres reservados que no se escapará.

0

Me doy cuenta de que esta pregunta y sus respuestas tienen algunos años, pero pensé que compartiría mi hallazgo cuando tuviera problemas para obtener compliance under .Net 4.5.

Si su código se está ejecutando en asp.net, simplemente establezca el proyecto en destino 4.5 y ejecute en una máquina con 4.5 o posterior, aún puede obtener el comportamiento 4.0. Debe asegurarse de que <httpRuntime targetFramework="4.5" /> esté configurado en web.config.

De this blog article on msdn,

Si no hay <httpRuntime targetFramework> atribuyen presente en Web.config, suponemos que la aplicación quería 4.0 peculiaridades comportamiento.

Cuestiones relacionadas