samedi 30 décembre 2017

Spring Data: Sécuriser le trie

Spring Data permet de simplifier différentes opérations telles que les requêtes, les tries et la pagination.

L'objet Pageable contient tous le nécessaire pour supporter un grid html. Les champs à trier, l'ordre du trie, le nombre de donnée maximale à afficher...

Spring Data n'est que pour la partie serveur. Si aucune vérification n'est effectuée du côté du serveur et que le champs est inexistant ou si vous utilisez un dto avec une structure différente de votre bean, une exception sera lancée.

@GetMapping(value = "/members")
public Page<MemberDto> getPagingMembers(String search, Pageable pageRequest) {
    return memberService.getMembers(search, pageRequest);
}

@GetMapping(value = "/members")
public Page<MemberDto> getPagingMembers(String search, Pageable pageRequest) {
    Pageable newPageRequest = BindingPageRequestHelpler.binding(BindingPageRequestHelpler.memberPageRequestSort(), pageRequest);
    return memberService.getMembers(search, newPageRequest);
}
 
Un moyen simple est decréer une classe qui remplacera le nom du champsreçu du côté web avec celui qui lui est lié du côté serveur.

Un dto nommé memberDto pourrait avoir un champ id et un champ name.
Le bean aura un champs memberId et un champ name;

public class BindingPageRequestHelpler {

    public static Map<String, String> memberPageRequestSort() {
        return Collections.unmodifiableMap(Stream.of(
            new SimpleEntry<>("Id", "memberId"),
            new SimpleEntry<>("name", "name"))
            .collect(Collectors.toMap((e) -> e.getKey(), (e) -> e.getValue())));
    }

    public static Pageable binding(Map<String, String> pageRequestSort, Pageable pageRequest) {

        Sort sort = pageRequest.getSort();
        PageRequest newPageRequest = null;
        List<Order> newOrders = new ArrayList<>();

        for (Iterator<Order> orderIterator = sort.iterator(); orderIterator.hasNext();) {
            Order order = orderIterator.next();
            String column = pageRequestSort.get(order.getProperty());
            if (column != null) {
                Order newOrder = new Order(order.getDirection(), column);
                newOrders.add(newOrder);
            }
            Sort newSorts = new Sort(newOrders);
            newPageRequest = new PageRequest(pageRequest.getPageNumber(), pageRequest.getPageSize(), newSorts);
        }
        return newPageRequest;
    }
}
Cette classe permet rapidement d'éviter de se rendre jusqu'à la couche DAO pour avoir une erreur.