Недопустимая страница 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&page.sort.dir=asc">Property X</a></th>
<th><a href="?page.sort=propertyY&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
по умолчанию, который вернет результат, не сортируемый вообще. Это, вероятно, самый бесшовный опыт, но может также привести к утомительным попыткам выяснить, почему результат не сортируется.