ошибка % декодирования springboot, когда она находится в URL и была экранирована

#spring-boot #escaping #decode #percentage

#весенняя загрузка #экранирование #декодировать #процент

Вопрос:

информация о версии:

Версия сервера: Apache Tomcat / 9.0.17
Сервер построен: 13 марта 2019 15:55:27 UTC
Номер сервера: 9.0.17.0
Название ОС: Windows 8.1
Версия ОС: 6.3
Архитектура: amd64
Версия JVM: 1.8.0_40-b25

spring-boot-2.1.4
spring-core-5.1.6

У меня есть HTML-страница, подобная этой: localhost/example/37%.html
(извините, я не могу запустить URL с http //, потому что страница редактирования автоматически изменит его на ссылку и добавит 25 после %)
когда я обращаюсь к этому URL, я получаю сообщение об ошибке: HTTP Status 400.
Так и должно быть, потому что % — это escape-символ.
поэтому я изменил URL на: localhost/example/37%.html .
на этот раз я получил новую ошибку:

Страница с ошибкой белой метки
В этом приложении нет явного сопоставления для / error, поэтому вы рассматриваете это как запасной вариант.
Чт, 03 сентября, 09:25:13 CST 2020
Произошла непредвиденная ошибка (тип = Внутренняя ошибка сервера, статус = 500).
URLDecoder: недопустимые шестнадцатеричные символы в шаблоне escape (%) — Для входной строки: «.h»

Я проверил консоль tomcat, она выводит сообщение об ошибке:

 2020-09-03 09:25:12 [http-nio-8080-exec-3] ERROR 
o.s.b.w.s.support.ErrorPageFilter - Forwarding to error page from request [/37%.html] due to exception [URLDecoder: Illegal hex characters in escape (%) pattern - For input string: ".h"]
java.lang.IllegalArgumentException: URLDecoder: Illegal hex characters in escape(%) pattern - For input string: ".h" 
at java.net.URLDecoder.decode(URLDecoder.java:194)  
at org.springframework.web.servlet.resource.PathResourceResolver.isInvalidEncodedPath(PathResourceResolver.java:285)
at org.springframework.web.servlet.resource.PathResourceResolver.isResourceUnderLocation(PathResourceResolver.java:254)
  

Похоже, что tomcat (или браузер) декодировал % до %, но springboot все еще декодирует % снова (PathResourceResolver.java )

Я не знаю, является ли это ошибкой или это правильный способ, которым springboot не разрешает % в URL

Ответ №1:

Я нашел кое-что интересное.

теперь у меня есть две веб-страницы, одна с именем 37%.html , другое имя 37%.html

Следуйте логике springboot, чтобы он дважды декодировал %, я получил доступ к этому URL:

localhost/example/37%25.html

и это покажет мне 37%.html , НО, это показывает мне 37%.html .

итак, сколько раз или как springboot декодировал %???

затем я нашел два файла класса в springboot:
ResourceHttpRequestHandler.java
PathResourceResolver.java

у всех них есть функция с именем: isInvalidEncodedPath()

код здесь:

ResourceHttpRequestHandler.isInvalidEncodedPath(путь)

 private boolean isInvalidEncodedPath(String path) {
    if(path.contains("%")) {
        try {
            String decodedPath = URLDecoder.decode(path, "UTF-8");
            if(this.isInvalidPath(decodedPath)) {
                return true;
            }

            decodedPath = this.processPath(decodedPath);
            if(this.isInvalidPath(decodedPath)) {
                return true;
            }
        } catch (UnsupportedEncodingException | IllegalArgumentException var3) {
            ;
        }
    }

    return false;
}
  

PathResourceResolver.isInvalidEncodedPath(resourcePath)

 private boolean isInvalidEncodedPath(String resourcePath) {
    if(resourcePath.contains("%")) {
        try {
            String decodedPath = URLDecoder.decode(resourcePath, "UTF-8");
            if(decodedPath.contains("../") || decodedPath.contains("..\")) {
                this.logger.warn("Resolved resource path contains encoded "../" or "..\": "   resourcePath);
                return true;
            }
        } catch (UnsupportedEncodingException var3) {
            ;
        }
    }

    return false;
}   
  

видите что-то другое?? они оба выполняют URLDecoder.decode(resourcePath, «UTF-8»), но перехватывают разные исключения.

при доступе к URL springboot вызовет функцию в этом порядке:

1 ResourceHttpRequestHandler.isInvalidEncodedPath(путь)
2 PathResourceResolver.isInvalidEncodedPath(resourcePath)

поэтому, когда нажимается /37%.html в ResourceHttpRequestHandler.isInvalidEncodedPath(путь), он получает /37%.html , потому что tomcat (или браузер) декодирует % до %. затем URLDecoder.decode(«/37%.html «, «UTF-8»), вызывает исключение IllegalArgumentException, перехватывается, но ничего не делает, возвращает false . В PathResourceResolver.isInvalidEncodedPath(resourcePath),URLDecoder.decode(«/37%.html «, «UTF-8»), вызывает исключение IllegalArgumentException, не отслеживается, генерирует исключение.

при нажатии /37%25.html в ResourceHttpRequestHandler.isInvalidEncodedPath(путь), он получает /37%.html , URLDecoder.decode(«/37%.html «, «UTF-8»), никаких проблем. В PathResourceResolver.isInvalidEncodedPath(resourcePath),URLDecoder.decode(«/37%.html «, «UTF-8»), также без проблем. затем отобразите 37%.html

Если вы просто наберете /37%.html вы получите ошибку 400, недопустимый URI: isHexDigit.

итак, к сожалению, URL, который имеет % char, не может быть доступен правильно.

Комментарии:

1. О, другой интересный. Если вы используете jrebel для отладки в IDEA, и вы не увидите ошибку.каждая страница хороша! потому что PathResourceResolver. isInvalidEncodedPath(resourcePath) вызываться не будет. Я не знаю ПОЧЕМУ …. (версия jrebel 2018.1.6)