Pengesahan dalam Spring Boot

1. Gambaran keseluruhan

Untuk mengesahkan input pengguna, Spring Boot memberikan sokongan yang kuat untuk tugas biasa, namun kritikal ini, langsung.

Walaupun Spring Boot menyokong penyatuan yang lancar dengan validator tersuai, standard de-facto untuk melakukan pengesahan adalah Hibernate Validator , pelaksanaan rujukan Bean Validation framework.

Dalam tutorial ini, kita akan melihat cara mengesahkan objek domain di Spring Boot .

2. Pergantungan Maven

Dalam kes ini, kita akan belajar bagaimana mengesahkan objek domain di Spring Boot dengan membina pengawal REST asas.

Pengawal terlebih dahulu akan mengambil objek domain, kemudian akan mengesahkannya dengan Hibernate Validator, dan akhirnya ia akan memasukkannya ke dalam pangkalan data H2 dalam memori.

Ketergantungan projek agak standard:

 org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-data-jpa   com.h2database h2 1.4.197 runtime 

Seperti yang ditunjukkan di atas, kami memasukkan web spring-boot-starter- dalam fail pom.xml kerana kami memerlukannya untuk membuat pengawal REST. Selain itu, mari kita periksa versi terkini spring-boot-starter-jpa dan pangkalan data H2 di Maven Central.

Bermula dengan Boot 2.3, kita juga perlu menambahkan pergantungan pengesahan spring-boot-starter :

 org.springframework.boot spring-boot-starter-validation 

3. Kelas Domain Mudah

Dengan kebergantungan projek kita sudah ada, kita perlu menentukan contoh kelas entiti JPA, yang peranannya hanya akan menjadi model pengguna.

Mari lihat kelas ini:

@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; @NotBlank(message = "Name is mandatory") private String name; @NotBlank(message = "Email is mandatory") private String email; // standard constructors / setters / getters / toString }

Pelaksanaan kelas entiti Pengguna kami memang cukup anemia, tetapi secara ringkasnya menunjukkan bagaimana menggunakan kekangan Bean Validation untuk mengekang nama dan bidang e - mel .

Demi kesederhanaan, kami mengekang bidang sasaran hanya menggunakan kekangan @NotBlank . Juga, kami menentukan mesej ralat dengan atribut mesej

Oleh itu, apabila Spring Boot mengesahkan contoh kelas, medan yang dibatasi tidak boleh kosong dan panjangnya yang dipangkas mestilah lebih besar daripada sifar .

Selain itu, Bean Validation memberikan banyak kekangan lain selain @NotBlank. Ini membolehkan kami mengaplikasikan dan menggabungkan peraturan pengesahan yang berbeza dengan kelas yang dikekang. Untuk maklumat lebih lanjut, sila baca dokumen pengesahan kacang rasmi.

Oleh kerana kami akan menggunakan Spring Data JPA untuk menyelamatkan pengguna ke pangkalan data H2 dalam memori, kami juga perlu menentukan antara muka repositori mudah untuk mempunyai fungsi CRUD asas pada objek Pengguna :

@Repository public interface UserRepository extends CrudRepository {}

4. Melaksanakan Pengawal REST

Sudah tentu, kita perlu menerapkan lapisan yang membolehkan kita mendapatkan nilai-nilai yang diberikan ke medan terhad objek Pengguna kita .

Oleh itu, kami dapat mengesahkannya dan melakukan beberapa tugas selanjutnya, bergantung pada hasil pengesahan.

Spring Boot menjadikan proses yang kelihatan rumit ini sangat mudah melalui pelaksanaan pengendali REST.

Mari lihat pelaksanaan pengendali REST:

@RestController public class UserController { @PostMapping("/users") ResponseEntity addUser(@Valid @RequestBody User user) { // persisting the user return ResponseEntity.ok("User is valid"); } // standard constructors / other methods } 

Dalam konteks Spring REST, pelaksanaan kaedah addUser () agak standard.

Sudah tentu, bahagian yang paling relevan adalah penggunaan anotasi @Valid .

Apabila Spring Boot menemui argumen yang diberi penjelasan dengan @Valid , secara automatik bootstraps pelaksanaan JSR 380 lalai - Hibernate Validator - dan mengesahkan argumen.

Apabila argumen sasaran gagal lulus pengesahan, Spring Boot membuang pengecualian MethodArgumentNotValidException .

5. Anotasi @ExceptionHandler

Walaupun Spring Boot mengesahkan objek Pengguna yang diteruskan ke kaedah addUser () secara automatik, sangat berguna , aspek yang hilang dari proses ini adalah bagaimana kita memproses hasil pengesahan.

The @ExceptionHandler anotasi membolehkan kami untuk mengendalikan jenis tertentu pengecualian melalui satu kaedah tunggal.

Oleh itu, kami dapat menggunakannya untuk memproses kesalahan pengesahan:

@ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public Map handleValidationExceptions( MethodArgumentNotValidException ex) { Map errors = new HashMap(); ex.getBindingResult().getAllErrors().forEach((error) -> { String fieldName = ((FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); errors.put(fieldName, errorMessage); }); return errors; }

Kami menentukan pengecualian MethodArgumentNotValidException sebagai pengecualian yang harus dikendalikan. Oleh itu, Spring Boot akan memanggil kaedah ini apabila objek Pengguna yang ditentukan tidak sah .

Kaedah menyimpan nama dan mesej ralat pasca pengesahan setiap medan tidak sah di Peta. Seterusnya ia menghantar Peta kembali kepada klien sebagai representasi JSON untuk proses selanjutnya.

Ringkasnya, pengawal REST membolehkan kita memproses permintaan dengan mudah ke titik akhir yang berbeza, mengesahkan objek Pengguna , dan mengirim respons dalam format JSON.

Reka bentuknya cukup fleksibel untuk menangani tindak balas pengawal melalui beberapa peringkat web, mulai dari mesin templat seperti Thymeleaf, hingga kerangka JavaScript yang lengkap seperti Angular.

6. Menguji REST Controller

Kami dapat menguji kefungsian pengawal REST kami dengan ujian integrasi.

Mari mulakan olok-olok / autowiring pelaksanaan antara muka UserRepository , bersama dengan contoh UserController , dan objek MockMvc :

@RunWith(SpringRunner.class) @WebMvcTest @AutoConfigureMockMvc public class UserControllerIntegrationTest { @MockBean private UserRepository userRepository; @Autowired UserController userController; @Autowired private MockMvc mockMvc; //... } 

Oleh kerana kami hanya menguji lapisan web, kami menggunakan anotasi @WebMvcTest . Ini membolehkan kita menguji permintaan dan respons dengan mudah menggunakan sekumpulan kaedah statik yang dilaksanakan oleh kelas MockMvcRequestBuilders dan MockMvcResultMatchers .

Sekarang mari kita menguji kaedah addUser () dengan objek Pengguna yang sah dan tidak sah yang dihantar dalam badan permintaan:

@Test public void whenPostRequestToUsersAndValidUser_thenCorrectResponse() throws Exception { MediaType textPlainUtf8 = new MediaType(MediaType.TEXT_PLAIN, Charset.forName("UTF-8")); String user = "{\"name\": \"bob\", \"email\" : \"[email protected]\"}"; mockMvc.perform(MockMvcRequestBuilders.post("/users") .content(user) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content() .contentType(textPlainUtf8)); } @Test public void whenPostRequestToUsersAndInValidUser_thenCorrectResponse() throws Exception { String user = "{\"name\": \"\", \"email\" : \"[email protected]\"}"; mockMvc.perform(MockMvcRequestBuilders.post("/users") .content(user) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(MockMvcResultMatchers.status().isBadRequest()) .andExpect(MockMvcResultMatchers.jsonPath("$.name", Is.is("Name is mandatory"))) .andExpect(MockMvcResultMatchers.content() .contentType(MediaType.APPLICATION_JSON_UTF8)); } } 

Selain itu, kami dapat menguji REST controller API menggunakan aplikasi pengujian kitaran hidup API percuma , seperti Postman.

7. Menjalankan Contoh Aplikasi

Akhirnya, kita dapat menjalankan projek contoh kita dengan kaedah utama () standard :

@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public CommandLineRunner run(UserRepository userRepository) throws Exception { return (String[] args) -> { User user1 = new User("Bob", "[email protected]"); User user2 = new User("Jenny", "[email protected]"); userRepository.save(user1); userRepository.save(user2); userRepository.findAll().forEach(System.out::println); }; } } 

Seperti yang dijangkakan, kita akan melihat beberapa objek Pengguna dicetak di konsol.

Permintaan POST ke // localhost: 8080 / endpoint pengguna dengan objek Pengguna yang sah akan mengembalikan String "User is valid".

Begitu juga, permintaan POST dengan objek Pengguna tanpa nama dan nilai e - mel akan mengembalikan respons berikut:

{ "name":"Name is mandatory", "email":"Email is mandatory" }

8. Kesimpulannya

Dalam artikel ini, kami mempelajari asas-asas melakukan pengesahan di Spring Boot .

Seperti biasa, semua contoh yang ditunjukkan dalam artikel ini terdapat di GitHub.