DATAJPA-1519 - Made the escapeCharacter itself available in SpEL expression.

Adapted documentation to reflect the changed API for escaping.
This commit is contained in:
Jens Schauder
2019-03-28 17:27:11 +01:00
committed by Oliver Drotbohm
parent 16661f7e7e
commit ee39e8863b
3 changed files with 21 additions and 8 deletions

View File

@@ -160,6 +160,7 @@ The JPA module supports defining a query manually as a String or having it being
Derived queries with the predicates `IsStartingWith`, `StartingWith`, `StartsWith`, IsEndingWith", `EndingWith`, `EndsWith`,
`IsNotContaining`, `NotContaining`, `NotContains`, `IsContaining`, `Containing`, `Contains` the respective arguments for these queries will get sanitized.
This means if the arguments actually contain characters recognized by `LIKE` as wildcards these will get escaped so they match only as literals.
The escape character used can be configured by setting the `escapeCharacter` of the `@EnableJpaRepositories` annotation.
Compare with <<jpa.query.spel-expressions>>.
==== Declared Queries
@@ -493,7 +494,7 @@ List<User> findByLastnameWithSpelExpression(@Param("lastname") String lastname);
====
When using `like`-conditions with values that are coming from a not secure source the values should be sanitized so they can't contain any wildcards and thereby allow attackers to select more data than they should be able to.
For this purpose the the `escape(String, String)` method is made available in the SpEL context.
For this purpose the the `escape(String)` method is made available in the SpEL context.
It prefixes all instances of `_` and `%` in the first argument with the single character from the second argument.
In combination with the `escape` clause of the `like` expression available in JPQL and standard SQL this allows easy cleaning of bind parameters.
@@ -502,13 +503,14 @@ In combination with the `escape` clause of the `like` expression available in JP
====
[source, java]
----
@Query("select u from User u where u.firstname like %?#{#escape([0],'#')}% escape '#'")
@Query("select u from User u where u.firstname like %?#{escape([0])}% escape ?#{escapeCharacter()}")
List<User> findContainingEscaped(String namePart);
----
====
Given this method declaration in an repository interface `findContainingEscaped("Peter_")" will find `Peter_Parker` but not `Peter Parker`.
Note that the method `escape(String, String)` available in the SpEL context will only escape the SQL and JPQL standard wildcards `_` and `%`.
The escape character used can be configured by setting the `escapeCharacter` of the `@EnableJpaRepositories` annotation.
Note that the method `escape(String)` available in the SpEL context will only escape the SQL and JPQL standard wildcards `_` and `%`.
If the underlying database or the JPA implementation supports additional wildcards these will not get escaped.
[[jpa.modifying-queries]]

View File

@@ -20,7 +20,7 @@ import lombok.Value;
import java.util.Arrays;
import java.util.List;
import org.springframework.util.Assert;
import org.springframework.lang.Nullable;
/**
* A value type encapsulating an escape character for LIKE queries and the actually usage of it in escaping
@@ -39,14 +39,25 @@ public class EscapeCharacter {
/**
* Escapes all special like characters ({@code _}, {@code %}) using the configured escape character.
*
* @param value must not be {@literal null}.
* @param value May be {@literal null}.
* @return
*/
@Nullable
public String escape(String value) {
Assert.notNull(value, "Value must be not null.");
if (value == null) {
return null;
}
return TO_REPLACE.stream() //
.reduce(value, (it, character) -> it.replace(character, this.value + character));
}
/**
* Makes the underlying character available.
*
* @return the value
*/
public char escapeCharacter() {
return value;
}
}

View File

@@ -559,7 +559,7 @@ public interface UserRepository
List<NameOnlyDto> findByNamedQueryWithConstructorExpression();
// DATAJPA-1519
@Query("select u from User u where u.firstname like %?#{escape([0])}% escape '\\'")
@Query("select u from User u where u.firstname like %?#{escape([0])}% escape ?#{escapeCharacter()}")
List<User> findContainingEscaped(String namePart);
interface RolesAndFirstname {