Недопустимая страница Spring Data JPA.параметры сортировки

в веб-приложении, которое использует Spring Data JPA с Hibernate, мы используем веб-страниц функции для обеспечения подкачки и сортировки в списках лиц.

@Controller
public class MyEntityController {
   @RequestMapping(method = RequestMethod.GET)
   public ModelAndView list(Pageable pageable) { ... }
}

@Configuration
public class MyWebMvcConfig extends WebMvcConfigurationSupport {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        super.addArgumentResolvers(argumentResolvers);
        argumentResolvers.add(new PageableArgumentResolver());
    }
}

public interface MyEntityRepository extends PagingAndSortingRepository<MyEntity, String> {
    Page<MyEntity> findByPropertyX(String propertyX, Pageable pagable);
}

это позволяет определять свойства сущности в отображаемом html как специальную сортировку параметры запроса, где page.sort значение фактически соответствует свойству в сущности, по которому должна выполняться сортировка.

<table>
    <thead>
        <tr>
            <th><a href="?page.sort=propertyX&amp;page.sort.dir=asc">Property X</a></th>
            <th><a href="?page.sort=propertyY&amp;page.sort.dir=asc">Property Y</a></th>
        </tr>
    </thead>
    <tbody>...</tbody>
</table>

это производит результирующий URL, такой как:

http://host/context-root/entities/?page.sort=propertyX&page.sort.dir=asc

проблема в том, что пользователи могут изменить URL-адрес для использования инвалидом page.sort свойства, которые либо ссылаются на несуществующие имена столбцов / свойств, либо хуже, которые используют недопустимые символы запроса JPA, которые приводят к недопустимому синтаксису.

например, если URL изменен для сортировки на "noSuchProperty":

http://host/context-root/entities/?page.sort=noSuchProperty&page.sort.dir=asc

но это свойство не существует следующее исключение:

java.lang.IllegalArgumentException: No property noSuchProperty found for type class com.my.company.MyEntity
    at org.springframework.data.repository.query.parser.Property.<init>(Property.java:76)
     . . .
    at org.springframework.data.repository.query.parser.AbstractQueryCreator.createQuery(AbstractQueryCreator.java:86)
     . . .
    at $Proxy68.findByPropertyX(Unknown Source)
    at com.my.company.MyEntityRepository.findByPropertyX(MyEntityRepository.java:17

аналогично, если URL-адрес изменяется на недопустимый символ синтаксиса запроса, например"":

http://host/context-root/entities/?page.sort=%22&page.sort.dir=asc

произойдет следующая ошибка:

java.lang.StackOverflowError
    java.util.regex.Pattern$GroupTail.match(Pattern.java:4227)
    . . .
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)
    org.springframework.data.repository.query.parser.Property.create(Property.java:326)

(существует также третий вкус исключений, который приводит к org.hibernate.QueryException когда @Query явно определяется в методе репозитория.)

Spring Data JPA абстрагирует детали сортировки, подкачки и обработки этих параметров; однако, похоже, он не изящно обрабатывает эти сценарии (т. е. где указан недопустимый параметр сортировки).

мы могли бы добавить некоторую дополнительную пользовательскую логику для проверки того, что свойство сортировки действительно существует на сущности; однако мне интересно, есть ли более чистый централизованный подход для этого, чтобы мы не теряли преимущества и простоту абстракций Spring Data JPA. Мы используем эту возможность сортировки во всем нашем приложении со многими различными объектами, поэтому в идеале нам нужен более общий подход, а не необходимость явно определите или проверьте свойства сортировки для каждой запрашиваемой страницы сущности.

в частности, мы фактически продлить PageableArgumentResolver чтобы принять аннотированное значение сортировки по умолчанию, которое предоставляется в нашем контроллере (не показано в примерах кода для простоты), поэтому мы хотели бы просто вернуться к этому порядку сортировки по умолчанию или просто порядку сортировки по умолчанию для сущности, а не создавать исключение.

идеи и попытки.. Я мог бы использовать QueryCreationListener для перехватите создание запроса и получите параметр сортировки; однако я не могу фактически изменить запрос в этот момент. Или, я могу расширить и использовать custom PageableArgumentResolver (мы уже делаем это), чтобы захватить параметры сортировки; однако у меня нет доступа к сущности в этот момент, ни возможности определить, действительно ли сущность имеет свойство с этим именем. Мы могли бы объявить поддерживаемые свойства явно; однако, опять же, это побеждает идею централизованной и автоматической обработки этого сценарий, не требующий конкретных или объявленных знаний объектов.

есть ли другой тип перехватчика или аналогичная конструкция, которую я могу использовать для централизованной проверки параметров сортировки по страницам и изменения, если это необходимо, перед вызовом запроса? Или есть ли какой-либо тип конфигурации или способ, которым Spring может автоматически обрабатывать этот сценарий, чтобы он более изящно обрабатывал недопустимые параметры сортировки?

2 ответов


Я смотрел на код, и я думаю, что еще немного трассировки стека было бы полезно. Но из того, что я вижу, я думаю, что есть два места, которые вы могли бы заняться, если вы в настроении переписать какой-то весенний код.

здесь есть два сценария, в первом из которых вы передаете Поле сортировки, которое не существует в объекте/таблице. Вы действительно хотите, чтобы этот плохой параметр молча игнорировался все время, а не только при передаче 1PageableArgumentResolver]1. Я думаю, что это должен быть вариант на AbstractQueryCreator (и, следовательно,JpaQueryCreator) игнорировать плохие параметры при сортировке.

вторая часть, которая должна быть решена, вероятно, является PageableArgumentResolver. Если вы передаете пустые строки или что-то, что не имеет смысла, как %20 тогда он должен игнорировать этот параметр и не отправлять его в PageRequest.

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


Я думаю, что улучшение PageableArgumentResolver для корректной обработки этих ситуаций. Он может попытаться создать PropertyPath экземпляр String сдал как Sort и, таким образом, убедитесь, что он действителен. Я немного разрываюсь на том, имеет ли смысл просто отбросить инвалида String по умолчанию, который вернет результат, не сортируемый вообще. Это, вероятно, самый бесшовный опыт, но может также привести к утомительным попыткам выяснить, почему результат не сортируется.

, он. Было бы здорово, если бы вы могли поднять билет JIRA для этого против Spring Data Commons и просто связать этот билет здесь. Не стесняйтесь открывать запрос на вытягивание, если у вас есть жизнеспособная реализация. Спасибо, что принесли это к столу уже!