Spring JPA data Invalid page.sort parameters

In a web application that uses Data JPA with Hibernate, we use the web pagination functionality to provide swap and sort capabilities into various object lists.

@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); } 

This allows you to define the properties of the entity in the rendered html as a special sorting of the query parameters , where the page.sort value really matches the property in the entity on which you want to 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> 

This creates a resulting URL, for example:

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

The problem is that users can change the URL to use invalid page.sort properties that refer to non-existent column / property names or, even worse, to use invalid JPA query characters that result in invalid syntax.

For example, if the URL is changed to sort by "noSuchProperty":

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

But this property does not exist, the following exception will be thrown:

 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 

Similarly, if the URL is changed to an invalid request syntax character, for example, "":

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

The following error will occur:

 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) 

(There is also a third flavor of exceptions, which leads to org.hibernate.QueryException when @Query explicitly defined in the repository method.)

Spring JPA data abstracts the details of sorting, swapping and processing these parameters; however, it does not seem to be able to handle these scripts (i.e., where an invalid sort parameter is specified).

We could add some additional user logic to verify that the sort property really exists in the entity; However, I am wondering if there is a cleaner, more centralized approach for this so that we do not lose the advantages and simplicity of Spring JPA data abstractions. We use this sorting function in our application with many different objects, so ideally we need a more general approach, instead of explicitly defining or checking the sorting properties for each requested page of the object.

In particular, we actually extend PageableArgumentResolver to accept the default annotated sort value that is presented in our controller (not shown in the code examples for simplicity), so we would like to simply discard this default sort order, or just the default sort order for object, not an exception.

Some ideas and attempts. I could use a QueryCreationListener to intercept the creation of the query and get the sort parameter; however, I cannot change the request at this point. Or I can extend and use a custom PageableArgumentResolver (we are already doing this) to capture the sorting options; however, I do not have access to the object at that time, and also can not determine whether the object really has a property under this name. We can declare supported properties explicitly; however, again, this defeats the idea of ​​centrally and automatically processing this scenario without requiring specific or declared knowledge of entities.

Is there any other type of interceptor or similar design that I can use to centrally check page sorting options and, if necessary, change them before invoking the request? Or is there some kind of configuration or way that Spring can automatically process this script so that it more elegantly handles invalid sorting options?

+6
source share
2 answers

I took a look at the code and I think stack tracing would be more useful. But from what I see, I think there are two places that you might want to decide if you have a desire to rewrite Spring code.

There are two scenarios here: in the first, you pass a sort field that does not exist in the object / table. What you really want is that this bad parameter will be ignored silently, all the time, and not just when passing to 1 PageableArgumentResolver ] 1 . I think it should be an AbstractQueryCreator option (and therefore a JpaQueryCreator ) to ignore the bad options in the sort.

The second part that should be resolved is probably PageableArgumentResolver . If you pass empty lines or something that doesn't make sense like %20 , then it should ignore this parameter and not send it to PageRequest .

Happy hack and good luck. Reading your post made me realize that my site is vulnerable to the same problem, and I really don't have a good solution.

+3
source

I think improving PageableArgumentResolver to gracefully handle these scripts. He can try to create an instance of the PropertyPath from String as a Sort and thus make sure that it is valid. I'm a little torn on whether it makes sense to simply reset the invalid String to default to return a result that doesn't sort at all. This is probably the easiest experience, but it can also lead to tedious attempts to figure out why the result is not sorted.

However, this. It would be great if you could raise your JIRA ticket at the expense of Spring Data Commons and just link this ticket here. Feel free to open a pull request if you have created a viable implementation. Thanks for bringing this to the table!

+1
source

Source: https://habr.com/ru/post/919171/


All Articles