Domanda

I valori di default di classe Uri a RFC 2396. Per OpenID e OAuth, ho bisogno di Uri fuggire coerente con RFC 3986.

System.Uri documentazione relativa alla classe :

  

Per impostazione predefinita, tutti i caratteri riservati nel URI sono scappati secondo RFC 2396. Questo comportamento cambia se Resource Identifiers internazionali o internazionale del nome di dominio di analisi è abilitata nel qual caso riservato caratteri nella URI sono fuggiti in conformità con RFC 3986 e RFC 3987.

La documentazione afferma anche che l'attivazione di questa modalità di IRI e quindi il comportamento RFC 3986 significa aggiungere un elemento di sezione di uri a machine.config e questo al file app / web.config:

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

Ma se questo è presente nel file .config o no, sto ottenendo lo stesso (non 3986) sfuggire il comportamento di SP1 App NET 3.5. Che altro devo fare per ottenere Uri.EscapeDataString di utilizzare la RFC 3986 regole? (in particolare, per sfuggire ai caratteri riservati come definito nella RFC che)

È stato utile?

Soluzione

Non essendo stato in grado di ottenere Uri.EscapeDataString ad assumere comportamenti RFC 3986, ho scritto il mio RFC 3986 compliant metodo di fuga. Esso sfrutta Uri.EscapeDataString, e poi 'aggiornamenti' la fuga a RFC 3986 la conformità.

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

Altri suggerimenti

Questo è stato effettivamente risolto in .NET 4.5 al lavoro di default, vedere qui .

Ho appena creato una nuova libreria chiamata purificare (dopo l'esecuzione in questo problema), che gestirà sempre questo a lavorare per .NET 4.5 (pre opere per 3,5) e Mono attraverso una variazione di approccio in questo posta . Purificare non cambia EscapeDataString ma non consente di avere Uris con caratteri riservati che non saranno sfuggiti.

Mi rendo conto che questa domanda e le risposte sono un paio di anni, ma ho pensato di condividere la mia scoperta quando ho avuto difficoltà a raggiungere la conformità sotto .Net 4.5 .

Se il codice è in esecuzione in asp.net, semplicemente impostando il progetto di destinazione 4.5 e in esecuzione su una macchina con 4.5 o versione successiva, si può ancora ottenere 4,0 comportamento. È necessario garantire <httpRuntime targetFramework="4.5" /> impostato nel web.config.

questo articolo del blog su MSDN ,

  

Se non c'è <httpRuntime targetFramework> attributo presente in   Web.config, si assume che l'applicazione ha voluto comportamento 4,0 stranezze.

Quale versione del framework stai usando? Sembra un sacco di questi cambiamenti sono stati effettuati nel ( da MSDN )" .NET Framework 3.5. 3.0 SP1 e 2.0 SP1" lasso di tempo.

non ho potuto trovare una risposta migliore (sia al 100% o 100% quadro reimplementazione), così ho creato questo abominio. Sembra funzionare 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();
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top