Косая черта в 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));
    }
}

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

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

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

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


person Mathias F    schedule 26.02.2009    source источник
comment
Гат Адамс рекомендует кодировку Base64 для любых параметров, которые могут содержать косую черту. Он также объясняет проблему более подробно: Запись в блоге: gathadams.com/2009/01/06/   -  person Tomalak    schedule 26.02.2009
comment
Вы также можете придумать другой способ замаскировать косую черту, скажем, заменить ее чем-то другим по соглашению. Я знаю. Это тоже некрасиво, но, по крайней мере, URL-адрес остается в некоторой степени читаемым.   -  person Tomalak    schedule 26.02.2009
comment
Я заметил, что косые черты и точки дают мне ошибки. Я сделал быстрый помощник, который заменяет их на -slash- и -dot-. Интересно, почему обычный Url.Encode / Decode что-то не работает. Кроме того, почему экранированный символ может выдавать какие-либо ошибки?   -  person Boris Callens    schedule 23.03.2009
comment
gathadams.com/2009/01/06/ выдает ошибку 404 - файл не найден.   -  person xraminx    schedule 22.04.2009
comment
Эй, партнерша! Кодировка Base64 также включает косую черту! Это не решение, на которое можно положиться.   -  person Andrew Arnott    schedule 14.11.2009
comment
Это не проблема кодирования с маршрутизацией; очевидно, это ошибка в классе .NET Uri. Согласно [моему прочтению] URI RFC, закодированные косые черты в пути не следует рассматривать как разделители сегментов. У MVC Routing нет шанса сделать это правильно, потому что класс Uri (неправильно) декодирует косые черты еще до того, как маршрутизация даже увидит их. См. Разделы 2.2 и 2.4 RFC. labs.apache.org/webarch/uri/rfc/rfc3986.html# зарезервировано   -  person Andrew Arnott    schedule 15.11.2009
comment
Что произойдет, если исходная строка содержит - или _?   -  person juan    schedule 03.12.2009
comment
Это правильно. Я не думаю, что.   -  person Tomalak    schedule 04.12.2009
comment
Какой символ в кодировке имеет косую черту?   -  person Mathias F    schedule 23.06.2012
comment
как упоминалось в URL-адресе, является допустимым символом base64, поэтому это не помогает   -  person Yauhen.F    schedule 25.02.2013
comment
@Yauhen Вы правы, как признается в моем предыдущем комментарии выше. OP не должен был принимать этот ответ. Чтобы исправить это, вывод ванильной кодировки Base64 можно исправить, заменив + и / на - и _ соответственно (и обратно на принимающей стороне). Это хорошо известный безопасный прием (сам алфавит Base64 не содержит - и _) и при этом дешевый. Это означает, что все еще можно использовать существующие библиотеки кодировщиков.   -  person Tomalak    schedule 25.02.2013


Ответы (10)


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

routes.MapRoute(
    "Default",                                                // Route name
    "{controller}/{action}/{*id}",                            // URL with parameters
    new { controller = "Home", action = "Index", id = "" });  // Parameter defaults
person mmx    schedule 26.02.2009
comment
Мне неудобно делать это в качестве общей практики, особенно на общедоступных веб-сайтах, но я сделал это в веб-приложении интрасети и не чувствую себя слишком виноватым. Спасибо, что указали на это решение! - person jkade; 19.06.2012
comment
@jkade (или кто угодно), почему вам не нравится это на общедоступном веб-сайте? - person wal; 17.09.2012
comment
Для тех, кто хочет только одного маршрута, вы можете сделать то же самое через RouteAttribute для действия вашего контроллера, например [Маршрут ({* id})] - person Vitaly; 27.07.2016
comment
Это буквально не помогает с% 5C. - person JoyalToTheWorld; 06.10.2016

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

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

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

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

person Andrew Arnott    schedule 16.11.2009
comment
Звучит здорово. Я воспользуюсь этим ответом после выпуска .NET 4.0. - person Mathias F; 17.11.2009
comment
Это не работает. Вы получаете синие подчеркивания в Visual Studio, и это, похоже, не действует. - person cdmckay; 22.06.2011
comment
Примечание. В официальном выпуске .NET 4 в MSDN указано что этот параметр можно добавить только в machine.config или application.config - НЕ в web.config. - person Stelloy; 08.12.2011
comment
Спустя годы проблема с .NET Framework 4.7.1 и классом Uri все еще остается проблемой. Очень много. Для меня это очень непонятное поведение. Обратите внимание, что для проектов библиотек классов эта проблема не возникает. - person Lorenzo Solano Martinez; 14.09.2018
comment
@StephenLloyd, это сработало для меня в web.config (приложение ASP.NET с использованием классической версии .NET Framework 4.7.1). - person Lorenzo Solano Martinez; 14.09.2018

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

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

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

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

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

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

person Don Rolling    schedule 09.03.2011
comment
Вы, как и я, также можете столкнуться с этой проблемой: Ошибка приложения: длина URL-адреса для этого запроса превышает настроенное значение maxUrlLength. Это можно решить, добавив это значение web.config: ‹system.web› ‹httpRuntime maxUrlLength = 1000 maxQueryStringLength = 2048 /› - person Don Rolling; 09.03.2011
comment
Просто и эффективно! Спасибо. - person nrod; 20.04.2016
comment
лучше напишите свой собственный веб-сервер - person Toolkit; 03.06.2017

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

http://localhost:5000/Home/About?100%2f200
person Jon Galloway    schedule 14.11.2009
comment
Хороший звонок, Джон. Это единственный безопасный способ, который я могу придумать. Это немного нарушает соглашение, но решает проблему, когда ваш идентификатор должен быть строкой из любых символов. - person Brian Genisio; 28.01.2013
comment
Я не думаю, что это глупо - я думаю, что это лучший вариант - но я думаю, что ваш пример неверен? Должно быть - / About? X = 100% 2f200 - нет ?? - person niico; 13.04.2017

То же самое для 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 
person simonox    schedule 28.09.2010

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

person silentnoise    schedule 16.03.2016

Это интересно в отношении .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);
    }
person BillB    schedule 21.11.2009

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

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

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

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

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

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

  • Избегает необходимости дополнительных процессов экранирования (при замене '/' специальным символом, например '!' Или '_')
  • Не полагается на какие-либо настройки сервера, такие как AllowEncodedSlashes для Apache
person Frosty Z    schedule 30.08.2011
comment
Это не работает с ASP.NET 4. По-прежнему отображается ошибка HTTP 400 - неверный запрос. - person Rn222; 13.11.2012
comment
Извините, если этот ответ предназначен для PHP / Apache. Я предполагаю, что такая же логика должна применяться к ASP.NET. Может, кто-нибудь до меня успеет его перевести под ASP.NET. Я оставляю свой ответ, так как считаю, что он может помочь, даже если используемые технологии разные (например, ответ @simonox) - person Frosty Z; 11.06.2015

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

person shijas km    schedule 22.06.2012
comment
UrlDecoding здесь не проблема, это маршрутизация внутри MVC и тот факт, что закодированные строки с косой чертой (% 2f) будут анализироваться в маршрутизации, как если бы они (% 2f) были частью URL-адреса. - person Rodi; 22.01.2014