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
Вот простое объяснение решения и суммирование того, что уже было сказано.
Сторона запроса:
- UrlEncode ваш путь.
- Замените "%" на "!".
- Сделайте запрос.
Сторона ответа:
- Заменить '!' с '%'.
- UrlDecode ваш путь.
- Используйте параметры так, как они были предназначены.
Промыть, повторить, наслаждайся.
В.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
, Это будет работать, я проверял.