Spring Security - @PreFilter dan @PostFilter

1. Gambaran keseluruhan

Dalam artikel ini, kita akan belajar bagaimana untuk menggunakan @PreFilter dan @PostFilter penjelasan kepada operasi selamat dalam aplikasi Spring.

Apabila digunakan bersama dengan maklumat utama yang disahkan, @PreFilter dan @PostFilter membolehkan kita menentukan peraturan keselamatan yang terperinci menggunakan Bahasa Ekspresi Musim Semi.

2. Memperkenalkan @PreFilter dan @PostFilter

Ringkasnya, @PreFilter dan @PostFilter anotasi digunakan untuk senarai penapis objek berdasarkan peraturan keselamatan adat kita menentukan.

@PostFilter menentukan peraturan untuk menyaring senarai kembali kaedah, dengan menerapkan peraturan itu ke setiap elemen dalam senarai . Sekiranya nilai yang dinilai benar, item tersebut akan disimpan dalam senarai. Jika tidak, item tersebut akan dikeluarkan.

@PreFilter berfungsi dengan cara yang sangat mirip, bagaimanapun, penyaringan diterapkan pada daftar yang disalurkan sebagai parameter masukan ke kaedah yang dijelaskan.

Kedua-dua penjelasan boleh digunakan pada kaedah atau jenis (kelas dan antara muka). Kami akan menggunakannya hanya pada kaedah sepanjang artikel ini.

Tesis anotasi tidak aktif secara lalai - kita perlu mendayakan mereka dengan @EnableGlobalMethodSecurity anotasi dan prePostEnabled = benar - dalam konfigurasi keselamatan kita:

@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { // ... }

3. Menulis Peraturan Keselamatan

Untuk menulis peraturan keselamatan dalam dua anotasi ini - kami akan menggunakan ungkapan Spring-EL; kita juga boleh menggunakan filterObject objek terbina dalam untuk mendapatkan rujukan elemen senarai tertentu yang sedang diuji.

Spring Security menyediakan banyak objek bawaan lain untuk membuat peraturan yang sangat spesifik dan tepat.

Sebagai contoh , kita boleh menggunakan @PreFilter untuk memeriksa sama ada harta penerima objek Tugas sama dengan nama pengguna yang sedang disahkan:

@PostFilter("filterObject.assignee == authentication.name") List findAll() { ... }

Kami telah menggunakan anotasi @PostFilter di sini kerana kami mahukan kaedah untuk melaksanakan dan mendapatkan semua tugas terlebih dahulu, dan mereka meneruskan setiap tugas dari senarai melalui peraturan penapis kami.

Oleh itu, jika pengguna yang disahkan adalah michael , senarai tugas terakhir yang dikembalikan oleh kaedah findAll hanya akan mengandungi tugas yang diberikan kepada michael , walaupun pangkalan data mempunyai tugas yang diberikan kepada jim dan pam .

Sekarang mari buat peraturan sedikit lebih menarik. Andaikan bahawa jika pengguna adalah pengurus, mereka dapat melihat semua tugas, tanpa mengira siapa mereka ditugaskan:

@PostFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name") List findAll() { // ... }

Kami telah menggunakan kaedah built-in hasRole untuk memeriksa sama ada pengguna yang disahkan mempunyai peranan sebagai PENGURUS. Sekiranya hasRole kembali benar, tugas tersebut akan disimpan dalam senarai akhir. Oleh itu, jika pengguna adalah pengurus, peraturan akan berlaku untuk setiap item dalam senarai. Oleh itu senarai akhir akan mengandungi semua item.

Sekarang mari kita tapis senarai yang dilalui sebagai parameter untuk kaedah simpan menggunakan @PreFilter :

@PreFilter("hasRole('MANAGER') or filterObject.assignee == authentication.name") Iterable save(Iterable entities) { // ... }

Peraturan keselamatan adalah sama dengan peraturan yang kami gunakan pada contoh @PostFilter . Perbezaan utama di sini adalah bahawa item senarai akan disaring sebelum kaedah dijalankan, sehingga memungkinkan kita membuang beberapa item dari daftar, mencegahnya disimpan dalam pangkalan data.

Jadi jim , yang bukan pengurus, mungkin cuba menyimpan senarai tugas, yang sebahagiannya ditugaskan untuk memanjakan . Walaupun hanya tugas-tugas yang diberikan kepada jim yang akan disertakan, yang lain akan diabaikan.

4. Prestasi pada Senarai Besar

@PreFilter benar-benar keren dan mudah digunakan, tetapi tidak cekap ketika berurusan dengan senarai yang sangat besar kerana operasi pengambilan akan mengambil semua data dan menerapkan penapis selepas itu.

Bayangkan, sebagai contoh, bahawa kita mempunyai ribuan tugas dalam pangkalan data kita dan kita ingin mengambil lima tugas yang kini ditugaskan untuk di- pam . Sekiranya kita menggunakan @PreFilter , operasi pangkalan data akan mengambil semua tugas terlebih dahulu, dan berulang-ulang melalui semuanya untuk menyaring tugas-tugas yang tidak ditugaskan untuk pam .

5. Kesimpulan

Artikel cepat menjelaskan bagaimana untuk mewujudkan mudah, tetapi menjamin, aplikasi yang menggunakan Spring Security @PreFilter dan @PostFilter penjelasan.

Lihat contoh kod lengkap di repositori Github ini.