2009-02-26 4 views
54

Мои карты является: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), похоже, работают.

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 Properly url encode space character

+2

Вы также можете придумать другой способ замаскировать косую черту, скажем, заменить ее чем-то другим по соглашению. Я знаю. Это тоже уродливо, но по крайней мере URL-адрес остается читаемым. – Tomalak

+2

Я заметил, что косые черты и точки дают мне ошибки.Я сделал быстрый помощник, который заменяет их «-slash-» и «-dot-». Подумайте, почему обычный Url.Encode/Decode не работает. Кроме того, почему беглый персонаж должен давать какие-либо ошибки? –

+7

Это не проблема кодирования с маршрутизацией; это, по-видимому, ошибка в классе .NET Uri. Согласно [моему чтению] URI RFC, кодированные косые черты в пути не должны рассматриваться как разделители сегментов. MVC Routing не имеет шансов получить это право, потому что класс Uri (неправильно) декодирует косые черты, прежде чем маршрутизация даже увидит его. См. Разделы 2.2 и 2.4 RFC. http://labs.apache.org/webarch/uri/rfc/rfc3986.html#reserved –

ответ

44

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

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

Спасибо, хороший ответ :) –

+0

Мне не нравится делать это как обычную практику, особенно на публичном веб-сайте, но я делал это на веб-сайте intranet и не чувствовал себя слишком виноватым в этом. Спасибо, что указали это решение! – jkade

+7

@jkade (или кто-нибудь) почему вам неудобно с этим на публичном веб-сайте? – wal

10

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

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

Хороший звонок, Джон. Это единственный безопасный способ, который я могу придумать. Это немного нарушает соглашение, но решает проблему, когда ваш идентификатор должен быть строкой любых символов. –

+0

Я не думаю, что это хромой - я думаю, что это лучший вариант - я думаю, что ваш пример неверен? Должно быть -/О? X = 100% 2f200 - нет? – niico

23

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

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

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

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

+0

Звучит здорово. Я буду использовать это как ответ после выхода .NET 4.0. –

+4

Это не работает. Вы получаете синие подчеркивания в Visual Studio, и это, кажется, не имеет никакого эффекта. – cdmckay

+10

Примечание. Начиная с официального выпуска .NET 4, [MSDN] (http://msdn.microsoft.com/en-us/library/ee656542.aspx) говорится, что этот параметр можно добавить только в machine.config или application.config - НЕ web.config. –

0

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

Если мне нужен 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); 
    } 
9

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

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

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

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

http://tomcat.apache.org/security-6.html - Fixed in Apache Tomcat 6.0.10

important: Directory traversal CVE-2007-0450

Tomcat permits '\', '%2F' and '%5C' [...] .

The following Java system properties have been added to Tomcat to provide additional control of the handling of path delimiters in URLs (both options default to false):

  • org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true|false
  • org.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH: true|false

Due to the impossibility to guarantee that all URLs are handled by Tomcat as they are in proxy servers, Tomcat should always be secured as if no proxy restricting context access was used.

Affects: 6.0.0-6.0.9

Так что, если вы получили URL с% 2F характер, Tomcat возвращает: "400 Invalid URI: noSlash"

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

set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true 
20

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

Запрос сторона:

  1. UrlEncode ваш путь.
  2. Замените '%' на '!'.
  3. Оформить заявку. сторона

Ответ:

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

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

+1

Вы можете, как и я, также столкнуться с этой проблемой: Ошибка приложения: длина URL-адреса этого запроса превышает настроенное значение maxUrlLength. Она может быть решена путем добавления этого значения web.config: \t \t

+1

Простой и эффективный! Благодарю. – nrod

+0

лучше написать собственный веб-сервер – Toolkit

-1

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

  • Кодирование '/' до '% 2F' перед тем urlencode()
  • Decode '% 2F' к '/' после того, как (при необходимости) urldecode()

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

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

  • исключает необходимость дополнительных процессов, вылетающих («!», Если заменить «/» с особым характером, как и «_»)
  • Do не полагается на любом сервере настройки, такие как AllowEncodedSlashes для Apache
+0

Это не работает с ASP.NET 4. Он по-прежнему говорит об ошибке HTTP 400 - Bad Request. – Rn222

+0

Извините, если этот ответ предназначен для PHP/Apache. Я предполагаю, что такая же логика должна применяться для ASP.NET. Может быть, у кого-то будет время «перевести» его для ASP.NET передо мной. Я оставляю свой ответ, поскольку я думаю, что это может помочь, даже если используемые технологии отличаются (например, ответ @simonox). –

-3

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

+0

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

1

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

Смежные вопросы