URL-кодированная косая черта в URL

Моя карта это:

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Кажется, работает.

РЕДАКТИРОВАТЬ:

Кодировать 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 он отличается

9 ответов

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

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

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

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

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

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

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

Промыть, повторить, наслаждайся.

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

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

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

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

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

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

То же самое для 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: true | false
  • org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: true | false

Из-за невозможности гарантировать, что все 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 

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

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам