Ushbu bo'limda servletlar asosidagi dasturlarda Spring Security ning yuqori darajadagi arxitekturasi muhokama qilinadi.
Filtrlar haqida qisqacha ma'lumot
Spring Security ning servletlar qo‘llab-quvvatlashi servlet Filter ning ekzemplarlari asosida qurilgan, shuning uchun avval Filter ning umumiy rolini ko‘rib chiqish foydali. Quyidagi rasmda bitta HTTP-so'rov uchun odatiy darajali ishlov beruvchilar tuzilishi ko'rsatilgan.
Client ilovaga so'rov yuboradi va konteyner FilterChain ni yaratadi, bu esa so‘rov URI yo‘li asosida HttpServletRequest ni qayta ishlashi kerak bo'lgan Filter va Servlet ning ekzemplarlari tarkibini o‘z ichiga oladi. Spring MVC dasturida Servlet DispatcherServlet ning bir nusxasidir. Faqat bitta Servlet bitta HttpServletRequest va HttpServletResponse ni qayta ishlay oladi. Biroq, bir nechta Filter dan foydalanish mumkin:
-
Pastki
FilteryokiServletni chaqiroqdan to‘xtatish. Bunday holdaFilterodatdaHttpServletResponsega yozadi. -
Keyingi
FiltervaServletlar tomonidan ishlatiladiganHttpServletRequestyokiHttpServletResponseni o‘zgartirish
Filter quvvati unga uzatilgan FilterChain ga bog'liq.
FilterChain ni qo'llash misoli
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// dasturilla qolgan qismini bajarishdan oldin biror ish qilamiz
chain.doFilter(request, response); // dasturilla qolgan qismini chaqiramiz
// dasturilla qolgan qismini bajargandan keyin biror ish qilamiz
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// dasturilla qolgan qismini bajarishdan oldin biror ish qilamiz
chain.doFilter(request, response) // dasturilla qolgan qismini chaqiramiz
// dasturilla qolgan qismini bajargandan keyin biror ish qilamiz
}
Filter faqat pastki Filter va Servlet ga ta'sir qilganligi sababli, har bir Filter ni chaqirish tartibi juda muhim.
DelegatingFilterProxy
Spring DelegatingFilterProxy deb nomlangan Filter ning realizatsiyasini taqdim etadi, bu servlet konteynerining hayot aylanishi va Spring ning ApplicationContext o‘rtasida ko‘prik o‘rnatish imkonini beradi. Servlet konteyneri o‘z standartlarini ishlatib, Filter nusxalarini ro‘yxatga olish imkonini beradi, lekin u Spring da belgilangan beanlardan bexabar. DelegatingFilterProxy ni servlet konteynerining standart mexanizmlari orqali ro‘yxatdan o‘tkazish mumkin, ammo u butun ishni amalga oshirish uchun Spring beaniga delegatsiya qiladi.
Quyida DelegatingFilterProxy qanday qilib Filter va FilterChain ning nusxalari bilan ishlashini ko‘rib chiqamiz.
DelegatingFilterProxy ApplicationContext da Bean Filter0 ni qidiradi va keyin Bean Filter0 ni chaqiradi. Quyida DelegatingFilterProxy ning psevdokodi keltirilgan.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// Kechiktirilgan holatda Spring bean sifatida ro'yxatdan o'tgan filtrni olamiz
// Misol uchun, DelegatingFilterProxy ning delegati Bean Filter0 nusxasidir
Filter delegate = getFilterBean(someBeanName);
// Ishni Spring beaniga delegatsiya qilamiz
delegate.doFilter(request, response);
}
fun doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain) {
// Kechiktirilgan holatda Spring bean sifatida ro'yxatdan o'tgan filtrni olamiz
// Misol uchun, DelegatingFilterProxy ning delegati Bean Filter0 nusxasidir
val delegate: Filter = getFilterBean(someBeanName)
// Ishni Spring beaniga delegatsiya qilamiz
delegate.doFilter(request, response)
}
DelegatingFilterProxy ning yana bir afzalligi shundaki, u Filter bean nusxalarini qidirishni kechiktirish imkonini beradi. Bu muhim, chunki konteyner Filter nusxalarini konteyner ishga tushguncha ro‘yxatdan o‘tkazishi kerak. Biroq, Spring odatda ContextLoaderListener dan foydalanadi, bu Filter nusxalari ro‘yxatdan o‘tkazilgandan keyin yuklanadi.
FilterChainProxy
Spring Security dagi servletni qo‘llab-quvvatlash vositalari FilterChainProxy da joylashgan. FilterChainProxy – bu Spring Security tomonidan taqdim etilgan ixtisoslashtirilgan Filter, u SecurityFilterChain orqali bir necha Filter nusxalariga vakolat berishga imkon beradi. FilterChainProxy bean bo'lgani uchun u odatda DelegatingFilterProxy ga o‘ralgan.
SecurityFilterChain
SecurityFilterChain FilterChainProxy tomonidan Spring Security dan qaysi Filter ni chaqirish kerakligini aniqlash uchun ishlatiladi.
SecurityFilterChain dagi xavfsizlik filtrlari odatda beanlar bo‘lib, lekin ular DelegatingFilterProxy o‘rniga FilterChainProxy da ro‘yxatga olingan. FilterChainProxy servlet konteynerida yoki DelegatingFilterProxy da to‘g‘ridan-to‘g‘ri ro‘yxatdan o‘tkazishdan bir qator afzalliklar beradi. Birinchidan, u Spring Security ning barcha servlet qo‘llab-quvvatlash vositalari uchun boshlang‘ich nuqtani ta'minlaydi. Shu sababli, agar siz Spring Security ning servlet qo‘llab-quvvatlash vositalarida muammolarni bartaraf etishga harakat qilayotgan bo‘lsangiz, FilterChainProxy ga nuqta qo‘yish bilan boshlash eng yaxshisi.
IKkinchidan, chunki FilterChainProxy Spring Security dan foydalanganda markaziy o‘rinni egallaydi, u zarurligini inobatga olmagan vazifalarni bajarishi mumkin. Masalan, u SecurityContext ni tozalaydi, bu xotira oqishidan qochish uchun. Shuningdek, u Spring Security dan HttpFirewall ni qo‘llaydi, bu ilovalarni ma'lum turdagi hujumlardan himoya qiladi.
Bundan tashqari, qachon SecurityFilterChain ni chaqirish kerakligini aniqlashda katta moslashuvchanlikni ta'minlaydi. Servlet konteynerida Filter nuqsalari faqat URL-manzil asosida chaqiriladi. Biroq, FilterChainProxy HttpServletRequest da mavjud bo‘lgan hamma narsadan foydalangan holda chaqiruvni aniqlash uchun RequestMatcher interfeysidan foydalanishi mumkin.
Aslida, FilterChainProxy qaysi SecurityFilterChain ni ishlatish kerakligini aniqlash uchun ishlatilishi mumkin. Bu sizning dasturingizning turli qismlari uchun butunlay alohida sozlash imkonini beradi.
Bir necha SecurityFilterChain mavjud rasmda FilterChainProxy qaysi SecurityFilterChain ni ishlatish kerakligini hal qiladi. Faqat birinchi mos keluvchi SecurityFilterChain chaqiriladi. Agar /api/messages/ URL-manzili talab qilingan bo‘lsa, u avval /api/** orqali SecurityFilterChain0 ning momunosabati bilan solishtiriladi, shuning uchun SecurityFilterChain0 chaqiriladi, hatto SecurityFilterChainn ga ham mos kelsa. Agar /messages/ URL-manzili talab qilinsa, u /api/** orqali SecurityFilterChain0 ga mos kelmaydi, shuning uchun FilterChainProxy har bir SecurityFilterChain ni qidirishda davom etadi. SecurityFilterChainn ga mos keluvchi boshqa SecurityFilterChain nusxalari chaqirilmaydi deb taxmin qilinadi.
Diqqat, SecurityFilterChain0 faqat uchta Filter nusxasi bilan sozlangan. Biroq, SecurityFilterChainn to‘rtta Filter bilan sozlangan. Har bir SecurityFilterChain o‘zigacha bo‘lgan va alohida o‘rnatilishi mumkin bo‘lganligini eslatib o‘tish muhim. Darhaqiqat, SecurityFilterChain Filter ning nol nusxasiga ega bo‘lishi mumkin, agar dastur Spring Security ning muayyan so‘rovlarni e'tibordan chetda qoldirishini xohlagan bo‘lsa.
Xavfsizlik filtrlar
Spring Security ning filtleri FilterChainProxy orqali SecurityFilterChain uchun API orqali qo'shiladi. Filter nusxalari tartibi ahamiyatga ega. Odatda, Spring Security da Filter ni ketma-ketlikda kuzatishning keragi yo‘q. Shunga qaramay, ba'zi hollarda ularning qanday ketma-ketlikda joylashganligini bilish foydali.
Quyidagi Spring Security ning filtrlarining to‘liq tartibli ro‘yxati keltirilgan:
-
ForceEagerSessionCreationFilter -
ChannelProcessingFilter
-
WebAsyncManagerIntegrationFilter
-
SecurityContextPersistenceFilter
-
HeaderWriterFilter
-
CorsFilter
-
CsrfFilter
-
LogoutFilter
-
OAuth2AuthorizationRequestRedirectFilter
-
Saml2WebSsoAuthenticationRequestFilter
-
X509AuthenticationFilter
-
AbstractPreAuthenticatedProcessingFilter
-
CasAuthenticationFilter
-
OAuth2LoginAuthenticationFilter
-
Saml2WebSsoAuthenticationFilter
-
UsernamePasswordAuthenticationFilter -
OpenIDAuthenticationFilter
-
DefaultLoginPageGeneratingFilter
-
DefaultLogoutPageGeneratingFilter
-
ConcurrentSessionFilter
-
DigestAuthenticationFilter -
BearerTokenAuthenticationFilter
-
BasicAuthenticationFilter -
RequestCacheAwareFilter
-
SecurityContextHolderAwareRequestFilter
-
JaasApiIntegrationFilter
-
RememberMeAuthenticationFilter
-
AnonymousAuthenticationFilter
-
OAuth2AuthorizationCodeGrantFilter
-
SessionManagementFilter
-
ExceptionTranslationFilter -
FilterSecurityInterceptor -
SwitchUserFilter
Xavfsizlik istisnolarini qayta ishlash
ExceptionTranslationFilter AccessDeniedException va AuthenticationException ni HTTP-javoblarga aylantirish imkonini beradi.
ExceptionTranslationFilter xavfsizlik filtrlaridan biri sifatida FilterChainProxy ga qo'shiladi.
-
1 Dastlab
ExceptionTranslationFilterFilterChain.doFilter(request, response)ga murojaat qiladi, dasturiling boshqa qismini chaqirish uchun. -
2 Agar foydalanuvchi autentifikatsiya qilinmagan yoki
AuthenticationExceptionyuzaga kelgan bo‘lsa, autentifikatsiya protsedurasini boshlang.-
TheSecurityContextHolder tozalanadi
-
HttpServletRequestRequestCacheda saqlanadi. Foydalanuvchi muvaffaqiyatli autentifikatsiyalanganidan so‘ng,RequestCachedastlabki so‘rovni qayta ijro etish uchun ishlatiladi. -
AuthenticationEntryPointmijozdan autentifikatsiya ma'lumotlarini so‘rash uchun ishlatiladi. Masalan, u tizimga kirish sahifasiga yo‘naltirishi yokiWWW-Authenticatesarlavhasini yuborishi mumkin.
-
-
3 Boshqa holda, agar
AccessDeniedExceptionyuzaga kelsa, unda kirish rad etiladi.AccessDeniedHandlerkirishni rad qilishni boshqarish uchun chaqiriladi.
Agar dastur AccessDeniedException yoki AuthenticationException ni hosil qilmasa, ExceptionTranslationFilter hech narsa qilmaydi.
ExceptionTranslationFilter ning psevdokodi quyidagicha ko‘rinishi mumkin:
try {
// Ilovaning qolgan qismini chaqiramiz
filterChain.doFilter(request, response);
} catch (AccessDeniedException | AuthenticationException ex) {
if (!authenticated || ex instanceof AuthenticationException) {
// autentifikatsiya protsedurasini boshlaymiz
startAuthentication();
} else {
// kirishni rad qilamiz
accessDenied();
}
}
Filternusxalarining qisqacha sharhidanFilterChain.doFilter(request, response)chaqirishi dasturdan qolgan qismini chaqirishga teng ekanligini eslaymiz. Bu shuni anglatadiki, agar dasturdan boshqa bir qism (masalan,FilterSecurityInterceptoryoki xavfsizlik metodi)AuthenticationExceptionyokiAccessDeniedExceptionni hosil qilsa, unda bu istisnolar ushbu bosqichda ushlanadi va qayta ishlanadi.- Agar foydalanuvchi autentifikatsiya qilinmagan yoki
AuthenticationExceptionpaydo bo‘lsa, autentifikatsiya protsedurasini boshlang. - Aks holda, kirishni rad qilamiz
GO TO FULL VERSION