www how googleapis google español .net openid oauth escaping uri

.net - how - Cómo hacer que Uri.EscapeDataString cumpla con RFC 3986



oauth2 api (5)

La clase de Uri por defecto es RFC 2396. Para OpenID y OAuth, necesito que Uri se escape de manera consistente con RFC 3986.

De la documentación de la clase System.Uri :

De forma predeterminada, todos los caracteres reservados en el URI se escapan de acuerdo con RFC 2396. Este comportamiento cambia si los identificadores de recursos internacionales o el análisis del nombre de dominio internacional están habilitados, en cuyo caso los caracteres reservados en el URI se escapan de acuerdo con RFC 3986 y RFC 3987.

La documentación también indica que la activación de este modo IRI y, por tanto, el comportamiento del RFC 3986 significa agregar un elemento de sección uri a machine.config y esto a su archivo app / web.config:

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

Pero ya sea que 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 debo hacer para que Uri.EscapeDataString use las reglas RFC 3986? (específicamente, para escapar de los caracteres reservados como se define en ese RFC)


¿Qué versión del framework estás usando? Parece que muchos de estos cambios se realizaron en el marco de tiempo ".NET Framework 3.5. 3.0 SP1 y 2.0 SP1" ( de MSDN ).


Al no haber podido hacer que Uri.EscapeDataString asumiera el comportamiento de RFC 3986, escribí mi propio método de escape compatible con RFC 3986. Aprovecha Uri.EscapeDataString y luego ''actualiza'' el escape al cumplimiento de 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(); }


Esto realmente se ha corregido en .NET 4.5 para que funcione de forma predeterminada, consulte here .

Acabo de crear una nueva biblioteca llamada PUrify (después de encontrarme con este problema) que se encargará de que esto funcione para .NET pre 4.5 (funciona para 3.5) y Mono a través de una variación del enfoque en esta post . PUrify no cambia EscapeDataString pero le permite tener Uris con caracteres reservados que no se escaparán.


Me doy cuenta de que esta pregunta y las respuestas tienen algunos años, pero pensé que compartiría mi descubrimiento cuando tuviera problemas para cumplir con la norma .Net 4.5

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

De este artículo de blog en msdn ,

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


No pude encontrar una mejor respuesta (ya sea 100% en el marco o 100% de reimplementación), así 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(); } }