Yaylı güvenlik filtre zinciri, çok karmaşık ve esnek bir motordur.
Zincirdeki anahtar filtreler (sırayla)
- SecurityContextPersistenceFilter (Kimlik Doğrulamasını JSESSIONID'den geri yükler)
- UsernamePasswordAuthenticationFilter (kimlik doğrulaması gerçekleştirir)
- ExceptionTranslationFilter (FilterSecurityInterceptor'dan güvenlik istisnalarını yakala)
- FilterSecurityInterceptor (kimlik doğrulama ve yetkilendirme istisnaları atabilir)
Mevcut kararlı sürüm 4.2.1 belgelerine bakıldığında , bölüm 13.3 Filtre Sıralaması , tüm filtre zincirinin filtre organizasyonunu görebilirsiniz:
13.3 Filtre Sıralaması
Zincirde filtrelerin tanımlanma sırası çok önemlidir. Gerçekte hangi filtreleri kullanıyor olursanız olun, sıra aşağıdaki gibi olmalıdır:
ChannelProcessingFilter , çünkü farklı bir protokole yeniden yönlendirilmesi gerekebilir
SecurityContextPersistenceFilter , böylece bir SecurityContext, bir web isteğinin başlangıcında SecurityContextHolder'da kurulabilir ve SecurityContext'teki herhangi bir değişiklik, web isteği sona erdiğinde HttpSession'a kopyalanabilir (sonraki web isteğiyle kullanıma hazır)
ConcurrentSessionFilter , SecurityContextHolder işlevini kullandığından ve SessionRegistry'i müdürün devam eden isteklerini yansıtacak şekilde güncellemesi gerektiğinden
Kimlik doğrulama işleme mekanizmaları -
UsernamePasswordAuthenticationFilter , CasAuthenticationFilter ,
BasicAuthenticationFilter vb - böylece SecurityContextHolder geçerli bir Kimlik Doğrulama istek belirteci içerecek şekilde değiştirilebilir
SecurityContextHolderAwareRequestFilter , sen servlet kabın içine HttpServletRequestWrapper bir bahar Güvenlik farkında yüklemek için kullanıyorsanız
JaasApiIntegrationFilter bir eğer, JaasAuthenticationToken SecurityContextHolder olduğu bu JaasAuthenticationToken içinde Konu olarak FilterChain işleyecek
RememberMeAuthenticationFilter , böylece daha önceki hiçbir kimlik doğrulama işleme mekanizması SecurityContextHolder'ı güncellememişse ve istek, beni hatırla hizmetlerinin gerçekleşmesini sağlayan bir tanımlama bilgisi sunmuyorsa, uygun bir hatırlanan Kimlik Doğrulama nesnesi oraya yerleştirilecektir.
AnonymousAuthenticationFilter , böylece daha önceki hiçbir kimlik doğrulama işleme mekanizması SecurityContextHolder'ı güncellemediyse, oraya anonim bir Kimlik Doğrulama nesnesi yerleştirilecektir.
ExceptionTranslationFilter , herhangi bir Spring Security istisnasını yakalamak için bir HTTP hata yanıtı döndürülebilir veya uygun bir AuthenticationEntryPoint başlatılabilir
FilterSecurityInterceptor , web URI'lerini korumak ve erişim reddedildiğinde istisnalar oluşturmak
Şimdi sorularınıza tek tek devam etmeye çalışacağım:
Bu filtrelerin nasıl kullanıldığı kafam karıştı. İlkbaharda sağlanan form-login için, UsernamePasswordAuthenticationFilter yalnızca / login için kullanılıyor ve son filtreler kullanılmıyor mu? Form-login ad alanı öğesi bu filtreleri otomatik olarak yapılandırır mı? Her istek (kimliği doğrulanmış veya doğrulanmamış), oturum açma olmayan url için FilterSecurityInterceptor'a ulaşıyor mu?
Bir <security-http>
bölümü yapılandırdıktan sonra , her biri için en az bir kimlik doğrulama mekanizması sağlamalısınız. Bu, az önce bahsettiğim Bahar Güvenliği belgelerinin 13.3 Filtre Sıralaması bölümündeki 4. grupla eşleşen filtrelerden biri olmalıdır.
Bu, minimum geçerli güvenliktir: yapılandırılabilen http öğesi:
<security:http authentication-manager-ref="mainAuthenticationManager"
entry-point-ref="serviceAccessDeniedHandler">
<security:intercept-url pattern="/sectest/zone1/**" access="hasRole('ROLE_ADMIN')"/>
</security:http>
Sadece bunu yaparak, şu filtreler filtre zinciri proxy'sinde yapılandırılır:
{
"1": "org.springframework.security.web.context.SecurityContextPersistenceFilter",
"2": "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter",
"3": "org.springframework.security.web.header.HeaderWriterFilter",
"4": "org.springframework.security.web.csrf.CsrfFilter",
"5": "org.springframework.security.web.savedrequest.RequestCacheAwareFilter",
"6": "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter",
"7": "org.springframework.security.web.authentication.AnonymousAuthenticationFilter",
"8": "org.springframework.security.web.session.SessionManagementFilter",
"9": "org.springframework.security.web.access.ExceptionTranslationFilter",
"10": "org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
}
Not: Bunları, FilterChainProxy'yi @Autowires ve içeriğini döndüren basit bir RestController oluşturarak elde ederim:
@Autowired
private FilterChainProxy filterChainProxy;
@Override
@RequestMapping("/filterChain")
public @ResponseBody Map<Integer, Map<Integer, String>> getSecurityFilterChainProxy(){
return this.getSecurityFilterChainProxy();
}
public Map<Integer, Map<Integer, String>> getSecurityFilterChainProxy(){
Map<Integer, Map<Integer, String>> filterChains= new HashMap<Integer, Map<Integer, String>>();
int i = 1;
for(SecurityFilterChain secfc : this.filterChainProxy.getFilterChains()){
//filters.put(i++, secfc.getClass().getName());
Map<Integer, String> filters = new HashMap<Integer, String>();
int j = 1;
for(Filter filter : secfc.getFilters()){
filters.put(j++, filter.getClass().getName());
}
filterChains.put(i++, filters);
}
return filterChains;
}
Burada, <security:http>
öğeyi yalnızca bir minimum yapılandırmayla bildirerek , tüm varsayılan filtrelerin dahil edildiğini, ancak hiçbirinin Kimlik Doğrulama türünde olmadığını görebiliyoruz (13.3 Filtre Sıralaması bölümünde 4. grup). Yani aslında security:http
SecurityContextPersistenceFilter, ExceptionTranslationFilter ve FilterSecurityInterceptor öğesinin otomatik olarak yapılandırıldığı anlamına gelir.
Aslında, bir kimlik doğrulama işleme mekanizması yapılandırılmalı ve hatta bunun için talepleri işleyen güvenlik ad alanı fasulyeleri başlatma sırasında bir hata atıyor, ancak giriş noktası ref özniteliği eklenerek atlanabilir. <http:security>
<form-login>
Yapılandırmaya bir temel eklersem şu şekilde:
<security:http authentication-manager-ref="mainAuthenticationManager">
<security:intercept-url pattern="/sectest/zone1/**" access="hasRole('ROLE_ADMIN')"/>
<security:form-login />
</security:http>
Şimdi, filterChain şöyle olacak:
{
"1": "org.springframework.security.web.context.SecurityContextPersistenceFilter",
"2": "org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter",
"3": "org.springframework.security.web.header.HeaderWriterFilter",
"4": "org.springframework.security.web.csrf.CsrfFilter",
"5": "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter",
"6": "org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter",
"7": "org.springframework.security.web.savedrequest.RequestCacheAwareFilter",
"8": "org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter",
"9": "org.springframework.security.web.authentication.AnonymousAuthenticationFilter",
"10": "org.springframework.security.web.session.SessionManagementFilter",
"11": "org.springframework.security.web.access.ExceptionTranslationFilter",
"12": "org.springframework.security.web.access.intercept.FilterSecurityInterceptor"
}
Şimdi, bu iki filtre org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter ve org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter filtre oluşturulur ve FilterChainProxy'de yapılandırılır.
Öyleyse, şimdi sorular:
İlkbaharda sağlanan form-login için, UsernamePasswordAuthenticationFilter yalnızca / login için kullanılıyor ve son filtreler kullanılmıyor mu?
Evet, isteğin UsernamePasswordAuthenticationFilter url ile eşleşmesi durumunda bir oturum açma işleme mekanizmasını tamamlamaya çalışmak için kullanılır. Bu url, her istekle eşleşecek şekilde yapılandırılabilir veya hatta değiştirilebilir.
Aynı FilterchainProxy'de (HttpBasic, CAS, vb.) Yapılandırılmış birden fazla Kimlik Doğrulama işleme mekanizmasına sahip olabilirsiniz.
Form-login ad alanı öğesi bu filtreleri otomatik olarak yapılandırır mı?
Hayır, form-login öğesi, UsernamePasswordAUthenticationFilter'ı yapılandırır ve bir oturum açma sayfası url'si sağlamazsanız, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter'ı da yapılandırır, bu da basit bir otomatik oluşturulmuş oturum açma ile biter sayfa.
Diğer filtreler, yalnızca öznitelik içermeyen bir <security:http>
öğe oluşturularak varsayılan olarak otomatik olarak yapılandırılır security:"none"
.
Her istek (kimliği doğrulanmış veya doğrulanmamış), oturum açma olmayan url için FilterSecurityInterceptor'a ulaşıyor mu?
Her istek, talebin istenen URL'ye ulaşma hakkına sahip olup olmadığına dikkat eden unsur olduğu için ona ulaşmalıdır. Ancak daha önce işlenen filtrelerden bazıları, filtre zinciri işleminin çağrı yapmadan durmasına neden olabilir FilterChain.doFilter(request, response);
. Örneğin, istek csrf parametresine sahip değilse, bir CSRF filtresi filtre zinciri işlemeyi durdurabilir.
REST API'mi girişten alınan JWT belirteci ile güvenceye almak istersem ne olur? İki ad alanı yapılandırma http etiketini yapılandırmalıyım, haklar? / Login UsernamePasswordAuthenticationFilter
için diğeri ve REST url'leri için diğeri özel ile JwtAuthenticationFilter
.
Hayır, bu şekilde yapmak zorunda değilsiniz. Hem olduğuna dair karar UsernamePasswordAuthenticationFilter
ve JwtAuthenticationFilter
aynı http elemanda, ancak bu filtrelerin her somut davranışlarına bağlı. Her iki yaklaşım da mümkündür ve son olarak hangisinin seçileceği kendi tercihlerine bağlıdır.
İki http öğesinin yapılandırılması iki springSecurityFitlerChains oluşturur mu?
Evet bu doğru
Form-login beyan edene kadar UsernamePasswordAuthenticationFilter varsayılan olarak kapalı mı?
Evet, bunu yayınladığım yapılandırmaların her birinde yükseltilen filtrelerde görebilirsiniz
SecurityContextPersistenceFilter'ı, Kimlik Doğrulamasını JSESSIONID yerine mevcut JWT belirtecinden alacak olan bir tanesiyle nasıl değiştirebilirim?
Sadece yapılandırma SecurityContextPersistenceFilter önlemek olabilir oturumu stratejisini de <http:element>
. Sadece şu şekilde yapılandırın:
<security:http create-session="stateless" >
Veya, bu durumda, <security:http>
öğenin içine başka bir filtre ile üzerine yazabilirsiniz :
<security:http ...>
<security:custom-filter ref="myCustomFilter" position="SECURITY_CONTEXT_FILTER"/>
</security:http>
<beans:bean id="myCustomFilter" class="com.xyz.myFilter" />
DÜZENLE:
"Aynı FilterchainProxy'de yapılandırılmış birden fazla Kimlik Doğrulama işleme mekanizmasına sahip olabilirsiniz" hakkında bir soru. Birden çok (Yay uygulaması) kimlik doğrulama filtresi bildiriyorsa, ikincisi ilkinin gerçekleştirdiği kimlik doğrulamasının üzerine yazacak mı? Bunun birden çok kimlik doğrulama sağlayıcısına sahip olmakla nasıl bir ilgisi var?
Bu nihayet her filtrenin kendisinin uygulanmasına bağlıdır, ancak ikinci kimlik doğrulama filtrelerinin en azından önceki filtreler tarafından yapılan önceki kimlik doğrulamalarının üzerine yazabileceği gerçeği doğrudur.
Ancak bu zorunlu olarak olmayacak. Güvenli REST hizmetlerinde hem Http başlığı olarak hem de istek gövdesi içinde sağlanabilen bir tür yetkilendirme belirteci kullandığım bazı üretim durumlarım var. Bu yüzden, bir durumda Http Başlığından ve diğeri de kendi dinlenme isteğinin istek gövdesinden bu belirteci kurtaran iki filtre yapılandırıyorum. Bir http isteği kimlik doğrulama belirtecini hem Http başlığı olarak hem de istek gövdesi içinde sağlarsa, her iki filtrenin de onu yöneticiye yetkilendiren kimlik doğrulama mekanizmasını yürütmeye çalışacağı doğrudur, ancak isteğin basitçe kontrol edilip edilmediğinin kontrol edilmesinden kolayca kaçınılabilir doFilter()
her filtrenin yönteminin başlangıcında zaten kimliği doğrulanmıştır .
Birden fazla kimlik doğrulama filtresine sahip olmak, birden fazla kimlik doğrulama sağlayıcısına sahip olmakla ilgilidir, ancak bunu zorlamayın. Daha önce ifşa ettiğim durumda, iki kimlik doğrulama filtrem var, ancak yalnızca bir kimlik doğrulama sağlayıcım var, çünkü her iki filtre de aynı Kimlik Doğrulama nesnesini oluşturuyor ve her iki durumda da kimlik doğrulama yöneticisi onu aynı sağlayıcıya devrediyor.
Ve bunun tersine, sadece bir UsernamePasswordAuthenticationFilter yayınladığım, ancak kullanıcı kimlik bilgilerinin her ikisinin de DB veya LDAP'de yer alabileceği, bu nedenle iki adet UsernamePasswordAuthenticationToken destek sağlayıcım var ve AuthenticationManager'ın filtreden sağlayıcılara herhangi bir kimlik doğrulama girişimini delege ettiği bir senaryom var. kimlik bilgilerini güvenli bir şekilde doğrulamak için.
Bu nedenle, ne kimlik doğrulama filtrelerinin miktarının kimlik doğrulama sağlayıcılarının miktarını ne de sağlayıcı miktarının filtre miktarını belirlediğinin açık olduğunu düşünüyorum.
Ayrıca dokümantasyon, SecurityContextPersistenceFilter'ın, iş parçacığı havuzu nedeniyle önemli olan SecurityContext'in temizlenmesinden sorumlu olduğunu belirtir. Atlarsam veya özel uygulama sağlarsam, temizliği manuel olarak uygulamam gerekir, değil mi? Zinciri özelleştirirken daha benzer şeyler var mı?
Bu filtreye daha önce dikkatlice bakmadım, ancak son sorunuzdan sonra uygulanmasını kontrol ediyordum ve genellikle İlkbaharda olduğu gibi, neredeyse her şey yapılandırılabilir, genişletilebilir veya üzerine yazılabilir.
SecurityContextPersistenceFilter bir de delegeler SecurityContextRepository uygulanması SecurityContext arayın. Varsayılan olarak, bir HttpSessionSecurityContextRepository kullanılır, ancak bu, filtrenin yapıcılarından biri kullanılarak değiştirilebilir. Bu nedenle, ihtiyaçlarınıza uygun bir SecurityContextRepository yazmak ve her şeyi sıfırdan yapmaya başlamak yerine, kanıtlanmış davranışına güvenerek, SecurityContextPersistenceFilter'da yapılandırmak daha iyi olabilir.