Keamanan Musim Semi - @PreFilter dan @PostFilter

1. Ikhtisar

Pada artikel ini, kita akan belajar bagaimana menggunakan @PreFilter dan @PostFilter penjelasan untuk operasi yang aman dalam aplikasi Spring.

Saat digunakan bersama dengan informasi utama yang diautentikasi, @PreFilter dan @PostFilter memungkinkan kita untuk menentukan aturan keamanan yang terperinci menggunakan Spring Expression Language.

2. Memperkenalkan @PreFilter dan @PostFilter

Sederhananya, @PreFilter dan @PostFilter penjelasan yang digunakan untuk daftar filter objek berdasarkan aturan keamanan kustom kita mendefinisikan.

@PostFilter mendefinisikan aturan untuk memfilter daftar hasil dari suatu metode, dengan menerapkan aturan itu ke setiap elemen dalam daftar . Jika nilai yang dievaluasi benar, item tersebut akan disimpan dalam daftar. Jika tidak, item tersebut akan dihapus.

@PreFilter bekerja dengan cara yang sangat mirip, namun, pemfilteran diterapkan ke daftar yang diteruskan sebagai parameter input ke metode yang dianotasi.

Kedua anotasi dapat digunakan pada metode atau jenis (kelas dan antarmuka). Kami akan menggunakannya hanya pada metode di seluruh artikel ini.

Tesis penjelasan tidak aktif secara default - kita harus mengaktifkan mereka dengan @EnableGlobalMethodSecurity penjelasan dan prePostEnabled = true - dalam konfigurasi keamanan kami:

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

3. Menulis Aturan Keamanan

Untuk menulis aturan keamanan dalam dua anotasi ini - kita akan menggunakan ekspresi Spring-EL; kita juga dapat menggunakan objek filterObject bawaan untuk mendapatkan referensi ke elemen daftar tertentu yang sedang diuji.

Keamanan Musim Semi menyediakan banyak objek bawaan lainnya untuk membuat aturan yang sangat spesifik dan tepat.

Misalnya , kita dapat menggunakan @PreFilter untuk memeriksa apakah properti penerima tugas dari objek Tugas sama dengan nama pengguna yang saat ini diautentikasi:

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

Kami telah menggunakan anotasi @PostFilter di sini karena kami ingin metode untuk mengeksekusi dan mendapatkan semua tugas terlebih dahulu, dan mereka meneruskan setiap tugas dari daftar melalui aturan filter kami.

Jadi, jika pengguna yang diautentikasi adalah michael , daftar tugas akhir yang dikembalikan oleh metode findAll hanya akan berisi tugas yang ditetapkan ke michael , bahkan jika database memiliki tugas yang ditetapkan ke jim dan pam .

Sekarang mari kita buat aturannya sedikit lebih menarik. Asumsikan bahwa jika pengguna adalah manajer, mereka dapat melihat semua tugas, terlepas dari siapa mereka ditugaskan:

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

Kami telah menggunakan metode hasRole bawaan untuk memeriksa apakah pengguna yang diautentikasi memiliki peran MANAGER. Jika hasRole mengembalikan nilai true, tugas akan disimpan di daftar akhir. Jadi, jika pengguna adalah pengelola, aturan akan mengembalikan nilai true untuk setiap item dalam daftar. Jadi daftar terakhir akan berisi semua item.

Sekarang mari kita memfilter daftar yang diteruskan sebagai parameter ke metode penyimpanan menggunakan @PreFilter :

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

Aturan keamanan sama dengan yang kita gunakan pada contoh @PostFilter . Perbedaan utama di sini adalah item daftar akan disaring sebelum metode dijalankan, sehingga memungkinkan kita untuk menghapus beberapa item dari daftar, mencegahnya disimpan dalam database.

Jadi jim , yang bukan seorang manajer, dapat mencoba menyimpan daftar tugas, beberapa di antaranya ditugaskan ke pam . Namun hanya tugas yang ditugaskan ke jim yang akan dimasukkan, yang lainnya akan diabaikan.

4. Kinerja pada Daftar Besar

@PreFilter sangat keren dan mudah digunakan, tetapi bisa jadi tidak efisien saat menangani daftar yang sangat besar karena operasi pengambilan akan mengambil semua data dan menerapkan filter sesudahnya.

Bayangkan, misalnya, kita memiliki ribuan tugas di database kita dan kita ingin mengambil lima tugas yang saat ini ditetapkan ke pam . Jika kita menggunakan @PreFilter , operasi database akan mengambil semua tugas terlebih dahulu, dan mengulang semuanya untuk menyaring tugas yang tidak ditetapkan ke pam .

5. Kesimpulan

Artikel singkat ini menjelaskan cara membuat aplikasi yang sederhana, namun aman, menggunakan anotasi @PreFilter dan @PostFilter dari Spring Security .

Periksa contoh kode lengkap di repositori Github ini.