web-dev-qa-db-fra.com

Barre oblique encodée en URL

Ma carte est:

routes.MapRoute(
   "Default",                                             // Route name
   "{controller}/{action}/{id}",                          // URL with params
   new { controller = "Home", action = "Index", id = "" } // Param defaults
);

Si j'utilise l'URL http://localhost:5000/Home/About/100%2f200, il n'y a pas de route correspondante . Si je change l'URL en http://localhost:5000/Home/About/100, la route est à nouveau mise en correspondance.

Existe-t-il un moyen simple de travailler avec des paramètres contenant des barres obliques? Les autres valeurs échappées (espace %20) semblent fonctionner.

MODIFIER:

Encoder Base64 fonctionne pour moi. Cela rend l'URL moche, mais c'est OK pour le moment.

public class UrlEncoder
{ 
    public string URLDecode(string  decode)
    {
        if (decode == null) return null;
        if (decode.StartsWith("="))
        {
            return FromBase64(decode.TrimStart('='));
        }
        else
        {
            return HttpUtility.UrlDecode( decode) ;
        }
    }

    public string UrlEncode(string encode)
    {
        if (encode == null) return null;
        string encoded = HttpUtility.PathEncode(encode);
        if (encoded.Replace("%20", "") == encode.Replace(" ", ""))
        {
            return encoded;
        }
        else
        {
            return "=" + ToBase64(encode);
        }
    }

    public string ToBase64(string encode)
    {
        Byte[] btByteArray = null;
        UTF8Encoding encoding = new UTF8Encoding();
        btByteArray = encoding.GetBytes(encode);
        string sResult = System.Convert.ToBase64String(btByteArray, 0, btByteArray.Length);
        sResult = sResult.Replace("+", "-").Replace("/", "_");
        return sResult;
    }

    public string FromBase64(string decode)
    {
        decode = decode.Replace("-", "+").Replace("_", "/");
        UTF8Encoding encoding = new UTF8Encoding();
        return encoding.GetString(Convert.FromBase64String(decode));
    }
}

EDIT1:

À la fin, il s’est avéré que le meilleur moyen était de sauvegarder une chaîne bien formatée pour chaque élément à sélectionner. C’est bien mieux parce que maintenant je ne code que des valeurs et ne les décode jamais. Tous les caractères spéciaux deviennent "-". Beaucoup de mes tables de base de données ont maintenant cette colonne supplémentaire "URL". Les données sont assez stables, c'est pourquoi je peux aller de cette façon. Je peux même vérifier si les données dans "URL" sont uniques.

EDIT2:

Surveillez également le caractère de l'espace. Cela a l'air correct sur le serveur Web intégré VS mais est différent sur iis7 Caractère d'espace de codage de l'URL correct

55
Mathias F

Si ce n'est que votre dernier paramètre, vous pouvez faire:

routes.MapRoute(
    "Default",                                                // Route name
    "{controller}/{action}/{*id}",                            // URL with parameters
    new { controller = "Home", action = "Index", id = "" });  // Parameter defaults
47
Mehrdad Afshari

Dans .NET 4.0 beta 2, l'équipe CLR a proposé une solution de contournement.

Ajoutez ceci à votre fichier web.config:

<uri> 
    <schemeSettings>
        <add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
    </schemeSettings>
</uri>

Cela provoque le comportement de la classe Uri conformément à la RFC décrivant les URI, ce qui permet aux barres obliques d’être échappées dans le chemin sans s’échapper. L’équipe CLR signale qu’ils s’écartent de la spécification pour des raisons de sécurité. Le fait de le définir dans votre fichier .config vous incite essentiellement à prendre en charge les considérations de sécurité supplémentaires impliquées pour ne pas laisser les barres obliques dégagées.

24
Andrew Arnott

Voici une explication simple de la solution et un résumé de ce qui a déjà été dit.

Côté demande:

  1. UrlEncode votre chemin.
  2. Remplacez le '%' par '!'.
  3. Faites la demande.

Côté de la réponse:

  1. Remplace le '!' avec '%'.
  2. UrlDécode ton chemin.
  3. Utilisez les paramètres tels qu'ils étaient prévus.

Rincer, répéter, profiter.

21
Don Rolling

Une autre option consiste à utiliser une valeur de chaîne de requête. Très boiteux, mais plus simple que l'encodage personnalisé.

http://localhost:5000/Home/About?100%2f200
11
Jon Galloway

Même chose pour Java/Tomcat.

Il y a toujours un problème si vous avez un "/" codé (% 2F) dans votre URL.

RFC 3986 - Section 2.2 dit: "Si les données d'un composant URI sont en conflit avec le but d'un caractère réservé en tant que délimiteur, les données en conflit doivent être codées en pourcentage avant que l'URI ne soit formé." (RFC 3986 - Section 2.2)

Mais il y a un problème avec Tomcat: 

http://Tomcat.Apache.org/security-6.html - Corrigé dans Apache Tomcat 6.0.10

important: Traversée de répertoire CVE-2007-0450

Tomcat autorise les balises '\', '% 2F' et '% 5C' [...] 

Les propriétés système Java suivantes ont été ajoutés à Tomcat pour fournir contrôle supplémentaire du traitement de délimiteurs de chemin d'accès dans les URL (les deux options défaut à faux):

  • org.Apache.Tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: vrai | faux
  • org.Apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: vrai | faux

En raison de l'impossibilité de garantir que toutes les URL sont gérées par Tomcat en tant que ils sont dans des serveurs proxy, Tomcat doit toujours être sécurisé comme si non proxy restreignant l'accès au contexte était utilisé.

Affecte: 6.0.0-6.0.9

Donc, si vous avez une URL avec le caractère% 2F, Tomcat renvoie: "400 URI non valide: noSlash".

Vous pouvez activer le correctif dans le script de démarrage de Tomcat:

set Java_OPTS=%Java_OPTS% %LOGGING_CONFIG%   -Dorg.Apache.Tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 
9
simonox

Vous pouvez éviter les suggestions de double codage/décodage ci-dessus et utiliser simplement HttpServerUtility.UrlTokenEncode et le code UrlTokenDecode correspondant.

1
silentnoise

Pour le problème encodé '/' entrant, j'ai pu résoudre mon problème en ajoutant '*' pour capturer le paramètre id, puis en passant correctement un '/' dans le contrôle '/')

routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{*id}",
            defaults: new 
            { 
                controller = "Control", 
                action = "Action", 
                id = UrlParameter.Optional 
            })
0
user11406534

C’est intéressant pour .NET 4. Quoi qu’il en soit, ce lien décrit la RFC 1738 et inclut les caractères qui ont besoin d’être encodés et ceux qui sont simplement "dangereux" . link text

Si je veux une URL conviviale pour le référencement (comme lorsque vous voulez mettre un sujet de message de forum dans l'URL), ignorez le codage et remplacez tout ce qui n'est pas AZ, a-z, 0-9. 

public static string CreateSubjectSEO(string str)
    {
        int ci;
        char[] arr = str.ToCharArray();
        for (int i = 0; i < arr.Length; i++)
        {
            ci = Convert.ToInt32(arr[i]);
            if (!((ci > 47 && ci < 58) || (ci > 64 && ci < 91) || (ci > 96 && ci < 123)))
            {
                arr[i] = '-';
            }
        }
        return new string(arr);
    }
0
BillB