Закодированная косая черта (% 2F) с параметром пути Spring RequestMapping дает HTTP 400

Это не повторяющийся упомянутый вопрос, поскольку он специфичен для Spring. Тот, кто добавил это (через 3 года после факта!), Не удосужился прочитать ветку вопросов или комментариев, чтобы увидеть, каков был настоящий ответ. Принятый ответ - не совсем ответ, но автор ответа так и не вернулся и отредактировал его, как я просил.

Учитывая приведенный ниже метод успокоения, Spring 3.1 выдает ошибку 400 с «Запрос, отправленный клиентом, был синтаксически неверным ()». когда параметр token содержит косую черту в кодировке URL (% 2F), например "https://somewhere.com/ws/stuff/lookup/resourceId/287559/token/R4o6lI%2FbBx43/userName/jim "Без% 2F все работает нормально. Третья сторона уже звонит в эту службу (конечно!), Поэтому я не могу изменить то, что они отправляют, по крайней мере, в краткосрочной перспективе. Есть идеи, как обойти это на стороне сервера?

Эта проблема очень хорошо описана здесь https://jira.springsource.org/browse/SPR-8662 хотя эта проблема связана с UriTemplate, который я не использую, я могу сказать.

@RequestMapping("/ws/stuff/**")
@Controller
public class StuffController {
  @RequestMapping(value = "/ws/stuff/lookup/resourceId/{resourceId}/token/{token}/userName/{userName}", method = RequestMethod.GET)
   public @ResponseBody
   String provisionResource(@PathVariable("resourceId") String resourceId, @PathVariable("token") String token, @PathVariable("userName") String userName, ModelMap modelMap,
         HttpServletRequest request, HttpServletResponse response) {
      return handle(resourceId, userName, request, token, modelMap);
   }
}

Примечание: это на Glassfish 3.1.2, и сначала Grizzly / Glassfish не принимали косую черту, но

-Dcom.sun.grizzly.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

исправил это.

asadmin set configs.config.server-config.network-config.protocols.protocol.http-listener-2.http.encoded-slash-enabled=true

похоже, не помогло.


person Jim    schedule 20.11.2012    source источник
comment
Возможный дубликат urlencoded Прямая косая черта нарушает URL   -  person MJar    schedule 07.09.2016


Ответы (10)


Это может быть ваш ответ: urlencoded Прямая косая черта нарушает URL

Я бы посоветовал не помещать это в путь, вместо этого переместите его в параметр запроса.

Решение:

Вы можете изменить RequestMapping на

@RequestMapping(value = "/ws/stuff/lookup/resourceId/**", method = RequestMethod.GET) 

а затем вручную проанализируйте переменные пути из объекта запроса.

person Solubris    schedule 21.11.2012
comment
К сожалению, я не могу в ближайшее время изменить сторонний код. Я не использую Apache, как указано, хотя Grizzly имеет аналогичную конфигурацию, которую я уже отключил, как указано. Эта проблема сейчас возникает на уровне Spring. - person Jim; 21.11.2012
comment
В этом случае вы можете изменить RequestMapping на @RequestMapping (значение = / ws / stuff / lookup / resourceId / **, method = RequestMethod.GET), а затем вручную проанализировать переменные пути из объекта запроса. - person Solubris; 21.11.2012
comment
Дайте ответ, Литий, и я приму его :-) Это простой и разумный способ заставить это работать. Я говорю это, чтобы люди, которые придут и найдут это позже, быстро увидят хорошее решение. - person Jim; 21.11.2012
comment
У меня это не работает. Даже с / ** я всегда получаю 400, если в пути появляется% 2F. - person 30thh; 05.03.2013
comment
Простое исправление, но это действительно должно поддерживаться. Spring не должен декодировать путь до, пока не найдет соответствующее отображение. - person Josh M.; 12.08.2019
comment
В REST параметры пути и запроса имеют немного разные значения. Параметр пути является частью имени ресурса, а параметр запроса обычно является аргументом фильтра, передаваемым именованному ресурсу. Нет никаких технических причин, по которым имена ресурсов не могут содержать косую черту - именно для этого и предназначена кодировка URL. - person Greg Brown; 03.12.2020

для пружинной загрузки следующее помогло

@SpringBootApplication
public class Application extends WebMvcConfigurerAdapter {

    public static void main(String[] args) throws Exception {
        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }

}
person iamiddy    schedule 02.06.2016
comment
Это помогло с UrlPathHelperFixed, о котором упоминалось выше. Потому что иначе не получится с двойной косой чертой. И он правильно анализирует весь параметр пути и не требует взлома из запроса. - person saganas; 11.01.2017
comment
Я пробовал это с UrlPathHelperFixed из jira.spring.io/browse/SPR-11101 но это не сработало - person PAX; 25.07.2018
comment
... используя Spring Boot 1.5.9-RELEASE - person PAX; 25.07.2018
comment
Это также понадобится вам в Spring Boot 2: stackoverflow.com/a/48636757/636849 Чтобы избежать таких ошибок как RequestRejectedException: The request was rejected because the URL contained a potentially malicious String "%2F" - person Lucas Cimon; 08.02.2019

Для приложения с весенней загрузкой это сработало для меня ..

Версия 1 Добавить

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true

в ваш файл application.properties

Версия 2 запустите приложение весенней загрузки следующим образом.

static void main(String[] args) {
    System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
    SpringApplication.run this, args
}

Версия 3 или запустите приложение Java с -Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH = true

Эта фиксированная для меня переменная пути с косой чертой в кодировке% 2F.

person manukyanv07    schedule 25.02.2016

Обновление 2019 для Spring Boot 2+ / Spring (Security) 5+ / Java 8+:

Поскольку мое изменение в ответ iamiddy было отклонено, я также хочу предоставить полное решение для Spring Boot 2 + в качестве отдельного ответа.

WebMvcConfigurerAdapter устарел в Spring5 / Java8 и может быть заменен непосредственно интерфейсом WebMvcConfigurer, заканчивающимся:

@SpringBootApplication
public class Application extends WebMvcConfigurer {

    public static void main(String[] args) throws Exception {
        System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

Кроме того, вам также необходимо настроить Spring (Strict)HttpFirewall, чтобы избежать блокировки закодированных косых черт с сообщением об ошибке The request was rejected because the URL contained a potentially malicious String "%2F"

@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedSlash(true);    
    return firewall;
}

Spring Boot будет использовать указанный выше HttpFirewall Bean, когда он доступен - в противном случае может потребоваться настроить WebSecurity, как указано здесь:

person Ralf    schedule 09.10.2019
comment
Две вещи: во-первых, часть брандмауэра является необязательной, если вы, конечно, не используете spring -security, и во-вторых, если вы используете причал, просто переопределите метод configurePathMatch. Я не нашел ничего о пристани, только о том, что она должна работать, в отличие от tomcat, но это не тот случай, и мне пришлось это исправить. - person hocikto; 27.10.2020
comment
согласно документам Tomcat 9 свойство UDecoder.ALLOW_ENCODED_SLASH будет устарело. Так что это могло быть @Bean public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() { return factory -> factory.addConnectorCustomizers( connector -> connector.setEncodedSolidusHandling(PASS_THROUGH.getValue())); } - person leonid; 07.12.2020

Вот исправление для Spring 3.2.4 (должно работать и для других версий). Необходимо перезаписать UrlPathHelper по умолчанию

    public class UrlPathHelperFixed extends UrlPathHelper {

        public UrlPathHelperFixed() {
            super.setUrlDecode(false);
        }

        @Override
        public void setUrlDecode(boolean urlDecode) {
            if (urlDecode) {
                throw new IllegalArgumentException("Handler [" + UrlPathHelperFixed.class.getName() + "] does not support URL decoding.");
            }
        }

        @Override
        public String getServletPath(HttpServletRequest request) {
            return getOriginatingServletPath(request);
        }

        @Override
        public String getOriginatingServletPath(HttpServletRequest request) {
            return request.getRequestURI().substring(request.getContextPath().length());
        }
    }

И вставьте его в обработчик сопоставления:

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
        <property name="order" value="-1"></property>
        <property name="urlPathHelper">
            <bean class="com.yoochoose.frontend.spring.UrlPathHelperFixed"/>
        </property>
    </bean>

После дня тяжелой работы у меня все работает :-)

Команде Spring было предложено как https://jira.springsource.org/browse/SPR-11101

person 30thh    schedule 20.11.2013
comment
Хороший. Исправлено в Spring 3.2.8 согласно tkt. - person arun; 04.09.2014
comment
Использование этого исправления по-прежнему решает проблему для Spring 4.3.8; просто установка urlDecode = false, как было предложено в другом месте, не работает правильно во всех случаях (хотя для некоторых это работает нормально). - person Jules; 01.03.2018

Я нашел это решение, которое мне подходит;

System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");

непосредственно перед springApplication.run (args);

и добавьте ниже код в класс приложения

 @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
person Ankur Gupta    schedule 07.06.2016

Мы только что столкнулись с этой проблемой в моем офисе, мы сделали то, что было предложено выше из того, что Солюбрис сказал, где вы поместили это в параметр запроса. Единственное дополнительное требование - данные также могут иметь знак «&», что может испортить параметр запроса. Все, что нам нужно было сделать, это закодировать текст до того, как он будет отправлен в URL-адрес, и даже символы '&' были отфильтрованы.

person rsteier    schedule 10.04.2014

Другой ответ - дважды закодировать "/", что даст "%252F".
В вашей сопоставленной конечной точке Spring декодирует ее обратно в "%2F". Все, что вам нужно, это еще раз декодировать его, используя что-то вроде этого:

URLDecoder.decode(encoded_URL, "UTF-8");

person M. Sokólski    schedule 23.05.2019
comment
это было бы умно, но% 25 также признан злонамеренным. - person Sandro; 10.06.2021

Следующее решило проблему BACK_SLASH:

public static void main(String[] args) throws Exception {
  System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
  SpringApplication.run(Application.class, args);
}

Но те же функции можно было реализовать через application.yml.

org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH: true

Этот параметр не работает. Я не нашел для этого способа и все еще смотрю на это.

person Hakan Bali    schedule 22.07.2020
comment
Чтобы прояснить, обратная косая черта означает тот, который начинается в верхнем левом углу и пересекает нижний правый угол, а косая черта идет в другую сторону. URL-адреса имеют косую черту (https://www.stackoverflow.com), пути Windows имеют обратную косую черту (c:\windows), например. - person Jim; 22.07.2020

Чтобы избежать ручного анализа переменных, я сделал следующее:

  1. Перед выполнением любого другого кода добавьте следующее:
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
  1. И в контроллере добавьте 2 переменные вместо одной, например:
    @RequestMapping(value = "/api/devices-by-name/device={deviceId}/restconf/data/ietf-interfaces:interfaces-state/interface={dpuIdPrefix}/{dpuIdSuffix}",
            method = RequestMethod.GET,
            produces = "application/json")
    public ResponseEntity<String> getInterfaceState(@PathVariable(value = "deviceId") String deviceId,
                                                    @PathVariable(value = "dpuIdPrefix") String dpuIdPrefix,
                                                    @PathVariable(value = "dpuIdSuffix") String dpuIdSuffix) {
        String dpuId = dpuIdPrefix + "/" + dpuIdSuffix;

И с этим я могу получить следующее:

curl -s -X GET http://localhost:9090/api/devices-by-name/device=ZNSDX16DPU03/restconf/data/ietf-interfaces:interfaces-state/interface=gfast%200%2F14

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

person Jorge Matias    schedule 20.05.2021