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
, после чего маршрут снова сопоставляется.
Есть ли простой способ работы с параметрами, содержащими слэши? Другие escape-значения (пробел %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 кодирует символ пробела
Ответы
Ответ 1
Если это только ваш последний параметр, вы можете сделать:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{*id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" }); // Parameter defaults
Ответ 2
В .NET 4.0 beta 2 команда CLR предложила обходное решение.
Добавьте это в свой файл web.config:
<uri>
<schemeSettings>
<add name="http" genericUriParserOptions="DontUnescapePathDotsAndSlashes" />
</schemeSettings>
</uri>
Это приводит к тому, что класс Uri ведет себя в соответствии с RFC, описывающим URI, позволяя слэш-экранам сбежать на пути, не будучи неэкономным. Команда CLR сообщает, что они отклоняются от спецификации по соображениям безопасности, и установка этого в вашем файле .config в основном заставляет вас взять на себя ответственность за дополнительные соображения безопасности, связанные с не отменой косой черты.
Ответ 3
Здесь простое объяснение решения и суммирование того, что уже было сказано.
Сторона запроса:
- UrlEncode ваш путь.
- Замените '%' на '!'.
- Сделайте запрос.
Сторона ответа:
- Замените '!' с '%'.
- UrlDecode ваш путь.
- Используйте параметры, как они были предназначены.
Промойте, повторите, наслаждайтесь.
Ответ 4
Еще одна опция - использовать значение querystring. Очень хромой, но проще, чем пользовательская кодировка.
http://localhost:5000/Home/About?100%2f200
Ответ 5
То же самое для Java/Tomcat.
По-прежнему существует проблема, если у вас есть закодированный "/" (% 2F) в вашем URL-адресе.
RFC 3986 - В разделе 2.2 говорится: "Если данные для компонента URI будут конфликтуют с зарезервированным назначением символа в качестве разделителя, тогда конфликтующие данные должны быть закодированы до кодирования URI". (RFC 3986 - Раздел 2.2)
Но есть проблема с Tomcat:
http://tomcat.apache.org/security-6.html - Исправлено в Apache Tomcat 6.0.10
important: Обход каталога 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 startup script:
set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG% -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
Ответ 6
Вы можете избежать описанных выше предложений двойного кодирования/декодирования и просто использовать HttpServerUtility.UrlTokenEncode и соответствующий UrlTokenDecode.
Ответ 7
Это интересно о .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);
}
Ответ 8
Для входящей закодированной проблемы "/" я смог исправить свою проблему, добавив "*" для перехвата параметра id, а затем смог правильно передать закодированный "/" в элемент управления (параметр представлял собой строку с закодированной '/')
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{*id}",
defaults: new
{
controller = "Control",
action = "Action",
id = UrlParameter.Optional
})
Ответ 9
Как было предложено здесь, когда проблема возникла у разработчиков Symfony 1.x(+ предложено в Комментарии PHP для urlencode()
):
- Кодировать '/' до '% 2F' перед
urlencode()
- Декодировать '% 2F' до '/' после (если необходимо)
urldecode()
Примечание: вы можете использовать rawurlencode()
, но вам все равно придется дважды указывать '/'.
Преимущества:
- Избегает необходимости дополнительных процессов экранирования (если заменить "/" специальным символом типа "!" или "_" )
- Не полагайтесь на любые настройки сервера, такие как
AllowEncodedSlashes
для Apache
Ответ 10
Просто используйте Server.UrlDecode
. Он будет работать, я тестировал.