Apa gunanya DelegatingFilterProxy Spring MVC?

120

Saya melihat ini di aplikasi Spring MVC saya web.xml:

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

Saya mencoba mencari tahu mengapa itu ada dan apakah itu benar-benar dibutuhkan.

Saya menemukan penjelasan ini di dokumen Spring tetapi tidak membantu saya memahaminya:

Tampaknya menyarankan bahwa komponen ini adalah "perekat" antara servlet yang didefinisikan di web.xmldan komponen yang ditentukan di Musim Semi applicationContext.xml.

7.1 DelegatingFilterProxy

Saat menggunakan filter servlet, Anda jelas perlu mendeklarasikannya di Anda web.xml, atau mereka akan diabaikan oleh kontainer servlet. Dalam Keamanan Musim Semi, kelas filter juga merupakan kacang musim semi yang ditentukan dalam konteks aplikasi dan dengan demikian dapat memanfaatkan fasilitas injeksi ketergantungan Spring yang kaya dan antarmuka siklus hidup. Spring DelegatingFilterProxymenyediakan hubungan antara web.xmldan konteks aplikasi.

Saat menggunakan DelegatingFilterProxy, Anda akan melihat sesuatu seperti ini di web.xmlfile:

<filter>
   <filter-name>myFilter</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
   <filter-name>myFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Perhatikan bahwa filter sebenarnya adalah a DelegatingFilterProxy, dan bukan kelas yang akan menerapkan logika filter. Apa yang DelegatingFilterProxydilakukan adalah mendelegasikan metode Filter melalui kacang yang diperoleh dari konteks aplikasi Spring. Hal ini memungkinkan kacang mendapatkan keuntungan dari dukungan siklus hidup konteks aplikasi web Spring dan fleksibilitas konfigurasi. Kacang harus diimplementasikan javax.servlet.Filterdan harus memiliki nama yang sama seperti yang ada di elemen nama filter. Baca Javadoc untuk DelegatingFilterProxy untuk informasi lebih lanjut

Jadi, jika saya mengeluarkan ini dari saya web.xml, apa yang akan terjadi? Servletku tidak akan bisa berkomunikasi dengan wadah Spring? **

Thomas
sumber

Jawaban:

127

Ada semacam keajaiban di sini, tetapi pada akhirnya, semuanya adalah program deterministik.

The DelegatingFilterProxy adalah Filter seperti yang dijelaskan di atas, yang tujuannya adalah " mendelegasikan untuk kacang Spring-dikelola yang mengimplementasikan Filter antarmuka ", yaitu, ia menemukan kacang ( "Target kacang" atau "delegasi") dalam aplikasi Musim Semi Anda konteks dan memanggilnya. Bagaimana itu mungkin? Karena kacang ini mengimplementasikan javax.servlet.Filter, metode doFilter-nya dipanggil.

Kacang apa yang disebut? DelegatingFilterProxy "Mendukung" targetBeanName "[...], menentukan nama kacang target dalam konteks aplikasi Spring."

Seperti yang Anda lihat di web.xml Anda bahwa nama kacang adalah " springSecurityFilterChain " .

Jadi, dalam konteks aplikasi web, Filter membuat instance kacang yang disebut "springSecurityFilterChain" dalam konteks aplikasi Anda dan kemudian mendelegasikannya melalui metode doFilter ().

Ingat, konteks aplikasi Anda ditentukan dengan SEMUA file KONTEKS APLIKASI (XML). Misalnya: applicationContext.xml DAN applicationContext-security.xml.

Jadi cobalah untuk menemukan kacang bernama "springSecurityFilterChain" yang terakhir ...

... dan mungkin Anda tidak bisa (misalnya jika Anda mengikuti tutorial atau jika Anda mengkonfigurasi keamanan menggunakan Roo)

Inilah keajaibannya: ada elemen baru untuk mengkonfigurasi keamanan , seperti

<http auto-config="true" use-expressions="true"> 

karena diizinkan oleh http://www.springframework.org/schema/security/spring-security-3.0.xsd , akan berhasil.

Saat Spring memuat konteks aplikasi menggunakan file XML, jika menemukan elemen, Spring akan mencoba menyiapkan keamanan HTTP, yaitu, tumpukan filter dan URL yang dilindungi, serta mendaftarkan FilterChainProxy bernama "springSecurityFilterChain".

Sebagai alternatif, Anda dapat mendefinisikan kacang dengan cara klasik, yaitu:

<beans:bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">

Tetapi itu kurang disarankan, karena Anda perlu melakukan banyak konfigurasi (semua filter yang akan Anda gunakan. Dan ada lebih dari selusin di antaranya)

jbbarquero.dll
sumber
"applicationContext-security.xml DAN applicationContext-security.xml" adalah nama file yang sama dua kali.
musiKk
Terima kasih musiKk (Saya pikir Anda dapat mengedit posting secara langsung)
jbbarquero
Ini adalah penjelasan yang saya cari selama ini dan membereskan segalanya untuk saya.
pengguna871611
@jbbarquero: Anda benar, tetapi saya tidak yakin versi apa yang seharusnya. Saya cenderung membiarkan itu untuk diperbaiki oleh penulis asli agar tidak secara tidak sengaja mengubah artinya.
musiKk
BAIK. Bagaimanapun, saya sangat menghargai bantuan Anda untuk meningkatkan tanggapan saya. Sekali lagi terima kasih, musiKk
jbbarquero
73

Tahukah Anda apa itu Filter Servlet dan cara kerjanya? Ini adalah bagian yang sangat berguna dari Servlet Spec, memungkinkan kita untuk menerapkan konsep mirip AOP untuk melayani permintaan HTTP. Banyak kerangka kerja menggunakan penerapan Filter untuk berbagai hal, dan tidak jarang menemukan penerapan khusus darinya karena sangat mudah ditulis dan berguna. Di aplikasi Spring, sebagian besar hal yang dapat dilakukan aplikasi Anda ada di Spring beans. Sebuah contoh Filter, meskipun, dikendalikan oleh wadah Servlet. Penampung membuat instance, menginisialisasi, dan menghancurkannya. Servlet Spec tidak memerlukan integrasi Spring apa pun, jadi Anda memiliki konsep yang sangat berguna (Filter) tanpa cara mudah untuk mengikatnya ke aplikasi Spring Anda dan kacang yang melakukan pekerjaan itu.

Masuk ke DelegatingFilterProxy. Anda menulis implementasi Filter dan menjadikannya Spring bean, tetapi alih-alih menambahkan kelas Filter Anda sendiri ke web.xml, Anda menggunakan DelegatingFilterProxy, dan memberinya nama bean filter Anda dalam konteks Spring. (Jika Anda tidak secara eksplisit memberikan nama, itu menggunakan "nama-filter".) Kemudian pada waktu proses, DelegatingFilterProxy menangani kerumitan dalam menemukan implementasi yang sebenarnya - yang Anda tulis dan konfigurasikan di Spring - dan mengarahkan permintaan ke sana . Jadi pada waktu proses, seolah-olah Anda telah mendaftarkan filter Anda di web.xml, tetapi Anda mendapatkan keuntungan karena dapat menyambungkannya seperti kacang Spring lainnya.

Jika Anda mengambil pemetaan filter itu dari web.xml Anda, semuanya akan terus berfungsi, tetapi tidak ada URL Anda yang akan diamankan. (Itu mengasumsikan nama "springSecurityFilterChain" secara akurat menjelaskan apa yang dilakukannya.) Itu karena pemetaan ini memfilter setiap permintaan yang masuk dan menyerahkannya ke filter keamanan yang ditentukan dalam konteks Spring Anda.

Ryan Stewart
sumber
Terima kasih telah memposting komentar yang mencerahkan ini. Saya belajar Keamanan Musim Semi sekarang, mencoba memahaminya dengan cukup untuk melakukan penyesuaian. Saya tidak tahu apa itu filter servlet atau filter pegas. Sedikit Anda tentang AOP memperjelas MENGAPA seseorang akan memiliki filter daripada hanya menggunakan servlet ........ jadi Anda tidak perlu menulis pemrosesan pra / pasca yang sama berulang kali di setiap servlet / sumber daya
Steve
Wow. Penjelasan itulah yang saya butuhkan. Terima kasih telah membagikan pengetahuan Anda.
Charles Morin
@ Ryan Stewart jika saya memiliki dua kacang mengimplementasikan antarmuka Filter di applicationContext, dan saya ingin mengeksekusi dalam sebuah perintah, lalu bagaimana saya membuatnya?
Abhishek Nayak
@skaffman jika saya memiliki dua kacang mengimplementasikan antarmuka Filter di applicationContext, dan saya ingin mengeksekusi dalam urutan, lalu bagaimana saya membuatnya?
Abhishek Nayak
44

Apa itu Filter Servlet?

Filter servlet , secara umum, adalah konsep Java WebApp. Anda dapat memiliki filter servlet di aplikasi web apa pun, baik Anda menggunakan framework Spring atau tidak dalam aplikasi Anda.

Filter ini dapat mencegat permintaan sebelum mencapai servlet target. Anda dapat mengimplementasikan fungsionalitas umum, seperti otorisasi, dalam filter servlet. Setelah diterapkan, Anda dapat mengonfigurasi filter di web.xml Anda untuk diterapkan ke servlet tertentu, pola url permintaan khusus, atau semua pola url.

Dimana filter servlet digunakan?

Aplikasi web modern dapat memiliki lusinan filter seperti itu. Hal-hal seperti otorisasi, caching, manajemen sesi ORM, dan injeksi ketergantungan sering diimplementasikan dengan bantuan filter servlet. Semua filter ini harus terdaftar di web.xml.

Instantiating Servlet Filters - tanpa Spring Framework

Kontainer servlet Anda membuat instance Filter yang dideklarasikan web.xmldan memanggilnya pada waktu yang tepat (mis., Saat melayani permintaan servlet). Sekarang jika Anda seperti sebagian besar penggemar Dependency Injection (DI), Anda mungkin akan mengatakan bahwa pembuatan instance adalah hal yang lebih baik dari framework DI saya (Spring). Tidak bisakah saya membuat filter servlet saya dibuat dengan Spring sehingga bisa menerima semua kebaikan DI?

DelegatingFilterProxy, sehingga Spring membuat instance filter Anda

Di sinilah DelegatingFilterProxylangkah masuk DelegatingFilterProxyadalah impelmentasi javax.servlet.Filterantarmuka yang disediakan oleh Spring Framework. Setelah Anda mengkonfigurasi DelegatingFilterProxydi web.xml, Anda dapat mendeklarasikan kacang sebenarnya yang melakukan pemfilteran dalam konfigurasi pegas Anda. Dengan cara ini, Spring membuat instance kacang yang melakukan pemfilteran sebenarnya, dan Anda dapat menggunakan DI untuk mengkonfigurasi kacang ini.

Perhatikan bahwa Anda hanya memerlukan satu DelegatingFilterProxydeklarasi web.xmltetapi Anda dapat memiliki beberapa pemfilteran yang beandirangkai bersama dalam konteks aplikasi Anda.

Tahir Akhtar
sumber
dijelaskan dengan sangat baik.
pengguna4906240
15

Masalahnya, filter servlet dikelola oleh kontainer servlet, dan bukan oleh pegas. Dan Anda mungkin perlu menyuntikkan beberapa komponen pegas ke dalam filter Anda.

Jadi, jika Anda membutuhkan sesuatu seperti:

public class FooFilter {

    @Inject
    private FooService service;

    public void doFilter(....) { .. }

}

maka Anda memerlukan proxy filter yang mendelegasikan.

Bozho
sumber
1

Anda benar tentang 'lem'. Seperti yang tertulis di JavaDocs dari FilterChainProxy :

FilterChainProxy ditautkan ke rantai filter kontainer servlet dengan menambahkan deklarasi Spring DelegatingFilterProxy standar di file web.xml aplikasi.

Silakan lihat bagian FIlterChainProxy dari blog Di Balik Ruang Nama Keamanan Musim Semi untuk penjelasan yang sangat baik.

Ritesh
sumber
0

Saya bingung dengan "springSecurityFilterChain" di web.xml dan menemukan jawaban ini di dokumen keamanan springframework:

The <http>elemen merangkum konfigurasi keamanan untuk lapisan web aplikasi Anda. > Ini membuat kacang FilterChainProxy bernama "springSecurityFilterChain" yang memelihara tumpukan> filter keamanan yang menyusun konfigurasi keamanan web [19]. Beberapa filter inti selalu> dibuat dan yang lainnya akan ditambahkan ke tumpukan tergantung pada atribut elemen anak yang> ada. Posisi filter standar diperbaiki (lihat tabel urutan filter di> pengenalan ruang nama), menghapus sumber kesalahan umum dengan versi kerangka kerja sebelumnya> ketika pengguna harus mengkonfigurasi rantai filter secara eksplisit di kacang FilterChainProxy. Anda tentu saja dapat> tetap melakukan ini jika Anda memerlukan kontrol penuh atas konfigurasi.

Ini tautannya http://docs.spring.io/spring-security/site/docs/3.0.x/reference/appendix-namespace.html

Janet
sumber
0

Sudah lama sekali, tetapi saya memiliki pertanyaan yang sama dan saya menemukan ini: https://www.javacodegeeks.com/2013/11/spring-security-behind-the-scenes.html

Saya mencoba menjalankan proyek keamanan pegas saya dengan menghapus filter yang dimaksud dan juga menambahkannya. Apa yang saya temukan adalah jika kita menambahkan filter, maka panggilan akan dialihkan ke halaman login yang diperlukan seperti yang didefinisikan dalam konfigurasi spring-security.

Makanya, setuju dengan jawaban @ Ryan.

OutOfMind
sumber