URL-кодированная косая черта в URL - PullRequest
55 голосов
/ 26 февраля 2009

Моя карта:

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

Если я использую URL http://localhost:5000/Home/About/100%2f200, соответствующий маршрут отсутствует. Я изменяю URL на http://localhost:5000/Home/About/100, после чего маршрут снова совпадает.

Есть ли простой способ работы с параметрами, содержащими косую черту? Другие экранированные значения (пробел %20), похоже, работают.

EDIT:

Кодировать Base64 у меня работает. Это делает URL уродливым, но пока это нормально.

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:

В конце оказалось, что лучшим способом было сохранить красиво отформатированную строку для каждого элемента, который мне нужно выбрать. Это намного лучше, потому что теперь я только кодирую значения и никогда не декодирую их. Все специальные символы становятся «-». Многие из моих db-таблиц теперь имеют этот дополнительный столбец "URL". Данные довольно стабильны, поэтому я могу пойти по этому пути. Я даже могу проверить, уникальны ли данные в «URL».

EDIT2:

Также следите за пробелами. Он выглядит нормально на интегрированном веб-сервере VS, но отличается на iis7 Правильно url кодировать символ пробела

Ответы [ 10 ]

47 голосов
/ 26 февраля 2009

Если это только ваш последний параметр, вы можете сделать:

routes.MapRoute(
    "Default",                                                // Route name
    "{controller}/{action}/{*id}",                            // URL with parameters
    new { controller = "Home", action = "Index", id = "" });  // Parameter defaults
24 голосов
/ 17 ноября 2009

В .NET 4.0 beta 2 команда CLR предложила обходной путь.

Добавьте это в свой файл web.config:

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

Это приводит к тому, что класс Uri ведет себя в соответствии с RFC, описывающим URI, что позволяет экранировать косые черты в пути без экранирования. Команда CLR сообщает, что они отклоняются от спецификации по соображениям безопасности, и установка этого параметра в вашем файле .config в основном заставляет вас принять на себя дополнительные соображения безопасности, связанные с небрежным слешем.

21 голосов
/ 09 марта 2011

Вот простое объяснение решения и суммирование того, что уже было сказано.

Сторона запроса:

  1. UrlEncode вашего пути.
  2. Заменить '%' на '!'.
  3. Сделать запрос.

Сторона ответа:

  1. Заменить "!" с "%".
  2. UrlДекодируйте свой путь.
  3. Используйте параметры так, как они были предназначены.

Ополосните, повторите, наслаждайтесь.

11 голосов
/ 14 ноября 2009

Еще один вариант - использовать значение строки запроса. Очень хромая, но проще, чем пользовательская кодировка.

http://localhost:5000/Home/About?100%2f200
9 голосов
/ 28 сентября 2010

То же самое для Java / Tomcat.

Проблема все еще существует, если в вашем URL есть закодированный символ "/" (% 2F).

RFC 3986 - Раздел 2.2 гласит: «Если данные для компонента URI будут конфликтовать с целью зарезервированного символа в качестве разделителя, то конфликтующие данные должны быть закодированы в процентах до формирования URI». (RFC 3986 - раздел 2.2)

Но есть проблема с Tomcat:

http://tomcat.apache.org/security-6.html - Исправлено в Apache Tomcat 6.0.10

важно: обратный путь в каталогах CVE-2007-0450

Tomcat разрешает "\", "% 2F" и "% 5C" [...].

Следующие системные свойства Java были добавлены в Tomcat, чтобы обеспечить дополнительный контроль обработки разделители пути в URL (оба варианта по умолчанию false):

  • org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: правда | ложь
  • org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: правда | ложь

из-за невозможности гарантировать что все URL обрабатываются Tomcat как они находятся в прокси-серверах Tomcat всегда должен быть защищен, как будто нет прокси, ограничивающий доступ к контексту, был б.

Влияет: 6.0.0-6.0.9

Таким образом, если у вас есть URL с символом% 2F, Tomcat возвращает: «400 Invalid URI: noSlash»

Вы можете переключить исправление в скрипте запуска Tomcat:

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%   -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 
1 голос
/ 16 марта 2016

Вы можете избежать предложенных выше вариантов двойного кодирования / декодирования и просто использовать HttpServerUtility.UrlTokenEncode и соответствующий UrlTokenDecode.

0 голосов
/ 24 апреля 2019

Для входящей закодированной проблемы '/' я смог исправить проблему, добавив '*', чтобы поймать параметр id, а затем смог правильно передать закодированный '/' в элемент управления (параметр был строкой с закодированным '/')

routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{*id}",
            defaults: new 
            { 
                controller = "Control", 
                action = "Action", 
                id = UrlParameter.Optional 
            })
0 голосов
/ 22 июня 2012

Просто используйте Server.UrlDecode. Это будет работать, я проверял.

0 голосов
/ 30 августа 2011

Как предложено здесь , когда с проблемой столкнулись разработчики Symfony 1.x (+ предложено в комментариях PHP для urlencode()):

  • Кодировать «/» в «% 2F» до urlencode()
  • Декодировать '% 2F' в '/' после (при необходимости) urldecode()

Примечание: вы можете использовать rawurlencode(), но вам все равно придется дважды кодировать '/'.

Преимущества:

  • Избегает необходимости дополнительных экранирующих процессов (если заменить '/' специальным символом, таким как '!' Или '_')
  • Не полагаться на какие-либо настройки сервера, такие как AllowEncodedSlashes для Apache
0 голосов
/ 21 ноября 2009

Это интересно для .NET 4. В любом случае, эта ссылка описывает RFC 1738 и включает в себя, какие символы нуждаются в кодировании, а какие просто «небезопасны». текст ссылки

Если я хочу, чтобы URL, дружественный к SEO, (например, когда вы хотите поместить тему сообщения на форуме в URL), пропустите кодировку и замените все, что не A-Z, 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);
    }
...