GNU/Linux >> Znalost Linux >  >> Cent OS

Jak implementovat ověření pro RESTful Services s Spring

Ověření jarních fazolí

Ověřování dat není nové téma ve vývoji webových aplikací.

Krátce se podíváme na validaci dat v ekosystému Java obecně a konkrétně na Spring Framework. Platforma Java byla de facto standardem proimplementaci ověřování dat to je specifikace Bean Validation. Specifikace Bean Validation má několik verzí:

  • 1.0 (JSR-303),
  • 1.1 (JSR-349),
  • 2.0 (JSR 380) – nejnovější verze

Tato specifikace definuje sadu komponent, rozhraní a anotací. To poskytuje standardní způsob, jak omezovat parametry a návratové hodnoty metod a parametrů konstruktorů, poskytovat API pro ověřování objektů a objektových grafů.

Deklarativní model se používá k umístění omezení ve formě anotací na objekty a jejich pole. Jsou zde předdefinované anotace jako @NotNull , @Digits , @Pattern , @Email , @CreditCard . Existuje možnost vytvářet nová vlastní omezení.

Validace může probíhat ručně nebo přirozeněji, když jiná specifikace a rámce ověřují data ve správný čas, například zadáním uživatele, vložením nebo aktualizací v JPA.

Příklad ověření v jazyce Java

Pojďme se podívat na to, jak to lze provést v praxi v tomto jednoduchém příkladu Bean Validation v běžné Java aplikaci.

Máme objekt, který chceme ověřit se všemi poli anotovanými omezeními.

public class SimpleDto {

  @Min(value = 1, message = "Id can't be less than 1 or bigger than 999999")
  @Max(999999)
  private int id;

  @Size(max = 100)
  private String name;

  @NotNull
  private Boolean active;

  @NotNull
  private Date createdDatetime;

  @Pattern(regexp = "^asc|desc$")
  private String order = "asc";

  @ValidCategory(categoryType="simpleDto")
  private String category;
  …
  Constructor, getters and setters

Nyní jej můžeme použít v jednoduché Java aplikaci a ručně ověřit objekt.

public class SimpleApplication {

  public static void main(String[] args) {

    final SimpleDto simpleDto = new SimpleDto();
    simpleDto.setId(-1);
    simpleDto.setName("Test Name");
    simpleDto.setCategory("simple");
    simpleDto.setActive(true);
    simpleDto.setOrder("asc");
    simpleDto.setCreatedDatetime(new Date());

    ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
    Validator validator = validatorFactory.usingContext().getValidator();

    Set constrains = validator.validate(simpleDto);
    for (ConstraintViolation constrain : constrains) {

       System.out.println(
      "[" + constrain.getPropertyPath() + "][" + constrain.getMessage() + "]"
      );

    }

  }

}

A výsledek v Console bude:

“[id] [Id can't be less than 1 or bigger than 999999]”

Omezení ověření a anotace

Vytvořte vlastní ověřovací omezení a anotaci.


 @Retention(RUNTIME)
   @Target(FIELD)
   @Constraint(validatedBy = {ValidCategoryValidator.class})
   public @interface ValidCategory {

      String categoryType();

      String message() default "Category is not valid";

      Class<?>[] groups() default {};

      Class<? extends Payload>[] payload() default {};

    }

And constraint validation implementation:

public class ValidCategoryValidator implements ConstraintValidator<ValidCategory, String> {

    private static final Map<String, List> availableCategories;

    static {

      availableCategories = new HashMap<>();
      availableCategories.put("simpleDto", Arrays.asList("simple", "advanced"));

    }

    private String categoryType;

    @Override
    public void initialize(ValidCategory constraintAnnotation) {

      this.setCategoryType(constraintAnnotation.categoryType());

    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {

      List categories = ValidCategoryValidator.availableCategories.get(categoryType);
      if (categories == null || categories.isEmpty()) {

         return false;

      }

      for (String category : categories) {

         if (category.equals(value)) {

             return true;

      }

    }

    return false;

  }

}

Ve výše uvedeném příkladu pocházejí dostupné kategorie z jednoduché hash mapy. V reálných případech použití aplikací je lze získat z databáze nebo jiných služeb.

Vezměte prosím na vědomí, že omezení a ověření lze specifikovat a provádět nejen na úrovni pole, ale také na celém objektu.

Když potřebujeme ověřit různé závislosti polí, například počáteční datum, nemůže to být po datu ukončení.

Nejpoužívanější implementace Bean Validation specifikace jsou Hibernate Validator a Apache BVal .

Ověření pomocí Spring

Framework Spring poskytuje několik funkcí pro ověření.

  • Podpora pro Bean Validation API verze 1.0, 1.1 (JSR-303, JSR-349) byla zavedena ve Spring Frameworku počínaje verzí 3.
  • Spring má vlastní rozhraní Validator, které je velmi základní a lze jej nastavit v konkrétní instanci DataBinder. To by mohlo být užitečné pro implementaci ověřovací logiky bez anotací.

Ověření fazolí pomocí jara

Spring Boot poskytuje spuštěné ověření, které lze zahrnout do projektu:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
 </dependency>

Tento startér poskytuje verzi Hibernate Validator kompatibilní s aktuálním Spring Boot.

Pomocí funkce Bean Validation bychom mohli ověřit tělo požadavku, parametry dotazu, proměnné v cestě (např. / /simpledto/{id} ), nebo jakákoli metoda nebo parametry konstruktoru.

Požadavky POST nebo PUT

V požadavcích POST nebo PUT například předáme JSON payload, Spring jej automaticky převede na Java objekt a nyní chceme výsledný objekt validovat. Použijme SimpleDto objekt z 1 příkladu:

@RestController
@RequestMapping("/simpledto")
public class SimpleDtoController {

    @Autowired
    private SimpleDtoService simpleDtoService;

    @RequestMapping(path = "", method = RequestMethod.POST, produces = 
    "application/json")
    public SimpleDto createSimpleDto(

        @Valid @RequestBody SimpleDto simpleDto) {

      SimpleDto result = simpleDtoService.save(simpleDto);

      return result;

    }

}

Právě jsme přidali @Valid anotace k SimpleDto parametr anotovaný @RequestBody . Toto řekne Springu, aby zpracoval ověření před provedením skutečného volání metody. V případě, že se ověření nezdaří, Spring vyvolá MethodArgument NotValidException která ve výchozím nastavení vrátí odpověď 400 (Bad Request).

Ověřování proměnných cesty

Ověřování proměnných cesty funguje trochu jinak. Problém je v tom, že nyní musíme přidávat anotace omezení přímo do parametrů metody místo do objektů.

Aby to fungovalo, existují 2 možné možnosti:

Možnost 1:@Validated Anotace

Přidejte @Validated anotace do řadiče na úrovni třídy pro vyhodnocení omezujících anotací parametrů metody.

Možnost 2:Proměnná cesty

Použijte objekt, který představuje proměnnou path, jak je vidět v příkladu níže:

@RestController
@RequestMapping("/simpledto")
public class SimpleDtoController {

    @Autowired
    private SimpleDtoService simpleDtoService;

    @RequestMapping(path = "/{simpleDtoId}", method = RequestMethod.GET, produces = 
    "application/json")
    public SimpleDto getSimpleDto(

      @Valid SimpleDtoIdParam simpleDtoIdParam) {

    SimpleDto result = simpleDtoService.findById(simpleDtoIdParam.getSimpleDtoId());

    if (result == null) {

      throw new NotFoundException();

    }

    return result;

  }

}

V tomto případě máme SimpleDtoIdParam třída, která obsahuje simpleDtoId pole, které bude ověřeno podle standardní nebo vlastní anotace omezení Bean. Název proměnné cesty (/{simpleDtoId} ) by měl být stejný jako název pole (takže Spring bude moci najít nastavovače pro toto pole).

private static final long serialVersionUID = -8165488655725668928L;

    @Min(value = 1)
    @Max(999999)
    private int simpleDtoId;

    public int getSimpleDtoId() {
    return simpleDtoId;
    }

    public void setSimpleDtoId(int simpleDtoId) {
    this.simpleDtoId = simpleDtoId;
    }

}

Na rozdíl od Tělo požadavku ověření, Proměnná cesty ověření vyvolá ConstraintViolationException namísto MethodArgumentNotValidException . Proto budeme muset vytvořit vlastní obslužnou rutinu výjimek.

Framework Java Spring také umožňuje ověřování parametrů na úrovni služeb pomocí @Validated anotace (úroveň třídy) a @Valid (úroveň parametrů).

Vzhledem k tomu, že Spring JPA používá pod sebou Hibernate, podporuje Bean Validation i pro třídy entit. Vezměte prosím na vědomí, že pravděpodobně není dobrý nápad v mnoha případech spoléhat na tuto úroveň ověřování, protože to znamená, že veškerá logika se dříve zabývala neplatnými objekty.

Rozhraní Spring Validation

Spring definuje své vlastní rozhraní pro validaci Validator (org.springframework.validation.Validator). Lze jej nastavit pro konkrétní instanci DataBinder a implementovat ověření bez anotací (nedeklarativní přístup).

K implementaci tohoto přístupu bychom potřebovali:

  1. Implementujte rozhraní Validator
  2. Přidat validátor

Implementujte rozhraní Validator

Implementujte rozhraní Validator, například umožňuje pracovat s naším SimpleDto třída:

@Component
public class SpringSimpleDtoValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
    return SimpleDto.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {

      if (errors.getErrorCount() == 0) {

        SimpleDto param = (SimpleDto) target;
        Date now = new Date();
        if (param.getCreatedDatetime() == null) {

          errors.reject("100",

            "Create Date Time can't be null");

        } else if (now.before(param.getCreatedDatetime())) {

          errors.reject("101",

            "Create Date Time can't be after current date time");

        }

      }

    }

}

Zde zkontrolujte, zda je vytvořen Datetime časové razítko je v budoucnosti.

Přidat validátor

Přidejte implementaci Validator do DataBinder :

@RestController
@RequestMapping("/simpledto")
public class SimpleDtoController {

    @Autowired
    private SimpleDtoService simpleDtoService;

    @Autowired
    private SpringSimpleDtoValidator springSimpleDtoValidator;

    @InitBinder("simpleDto")
    public void initMerchantOnlyBinder(WebDataBinder binder) {
    binder.addValidators(springSimpleDtoValidator);
    }

    @RequestMapping(path = "", method = RequestMethod.POST, produces = 
    "application/json")
    public SimpleDto createSimpleDto(

      @Valid @RequestBody SimpleDto simpleDto) {

    SimpleDto result = simpleDtoService.save(simpleDto);
    return result;

  }

}

Nyní máme SimpleDto ověřeno pomocí omezujících anotací a naší vlastní implementace Spring Validation.


Cent OS
  1. Jak nakonfigurovat IMAP s SSL

  2. Jak přepsat adresy URL pomocí mod_rewrite pro Apache na Ubuntu 20.04

  3. Jak znovu vygenerovat initramfs a vmlinuz pro Rescue Kernel s aktuálním jádrem v CentOS/RHEL 7

  1. Jak spravovat služby Systemd pomocí Systemctl v systému Linux

  2. Jak skenovat server Debian na rootkity pomocí Rkhunter

  3. Jak nakonfigurovat subdoménu pro transakční e-mailové služby SMTP

  1. Jak spravovat služby Linux pomocí příkazu systemctl

  2. Jak vytvořit smyčku For s měnitelným počtem iterací?

  3. Jak nastavit limity zdrojů pro proces s Systemd v CentOS/RHEL 7 a 8