Próbuję wykombinować problem związany z Spring Security i SAML. Próbujemy użyć Spring Security (spring-security-core-3.1.1.RELEASE.jar) i SAML (spring-security-saml2-core-1.0.0-RC1-SNAPSHOT.jar), aby zmodyfikować nasz produkt jako SAML SP. EDYCJA: Tutaj jest (myślę!) Odpowiednie sekcji mojego xml kontekst związany z bezpieczeństwem. Jak widać, jest prawie identyczny z this sample XML.Spring Security i zagnieżdżony FilterChainProxy zapisujący dostawcę usług SAML
Symptomem jest to, że zaraz po uwierzytelnieniu z IDP strona mojego SP wyświetla się poprawnie; jednak zmiana adresu URL (np. kliknięcie dowolnego linku) natychmiast przesyła mnie z powrotem do IDP. Chyba zrozumiałem dlaczego, ale nie wiem, dlaczego nie zawsze tak jest.
Moje zrozumienie Spring Security polega na tym, że sprawdzanie autoryzacji opiera się na SecurityContextHolder. Mianowicie, umieść obiekt uwierzytelniający na uchwycie, a wszystko to sprawdza automatycznie. Następnie SecurityContextPersistenceFilter jest odpowiedzialny za utrzymanie repozytorium sesji do dopasowania.
Tak, jak ja prześledzić poprzez kod zabezpieczający Wiosna, widzę SecurityContextPersistenceFilter z następującego kodu:
SecurityContext contextBeforeChainExecution = repo.loadContext(holder);
try {
SecurityContextHolder.setContext(contextBeforeChainExecution);
chain.doFilter(holder.getRequest(), holder.getResponse());
} finally {
SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
// Crucial removal of SecurityContextHolder contents - do this before anything else.
SecurityContextHolder.clearContext();
repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
....
}
Tak daleko, tak dobrze. Następnie patrzę na FilterChainProxy i znajduję:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
doFilterInternal(request, response, chain);
} finally {
// SEC-1950
SecurityContextHolder.clearContext(); <------- Key line here
}
}
To nadal wydaje się być w porządku. Ponieważ FilterChainProxy powinien być wywoływany tylko raz, u podstawy wszystkich filtrów Spring Security, nie ma problemu z wyczyszczeniem SecurityContextHolder w tym momencie.
JEDNAK, to nie jest to, co się dzieje. To, co się faktycznie dzieje, to clearContext w FilterChainProxy nazywa się BEFORE SecurityContextPersistenceFilter otrzymuje szansę na odczytanie go z kontekstu do contextAfterChainExecution. Dzieje się tak dlatego, że FilterChainProxy faktycznie występuje dwa razy w łańcuchu połączeń. Wiem o tym, ponieważ ustawiłem punkt przerwania w FilterChainProxy.doFilter i jest on wywoływany dwa razy. Przy pierwszym wywołaniu ma inną instancję FilterChainProxy w swoim FilterChain. Oto stos Filtry zwrócony przez FilterChainProxy za getFilters metody:
org[email protected]78104d3c
org.spring[email protected]168c795e
FilterChainProxy[ Filter Chains: [ .... my patterns ] ],
org.sp[email protected]7fffde92
org.springframework.[email protected]e2d09d7
org.springfram[email protected]1c2b968f
o[email protected]395f222a
org[email protected]372e6f09
org.springfr[email protected]7dab91aa
Z tego łańcucha filtrów, ja nie rozumiem, jak SecurityContextPersistenceFilter może w ogóle działać: wydaje się, że SecurityContextHolder zawsze będzie czyszczony przed dostaje szansę aby to utrzymać.
Czy jest tu coś oczywistego? Czy nie rozumiem czegoś w Spring Security (bardzo możliwe!)
Dziękujemy za opublikowanie rozwiązania. Zmierzyłem się z tą samą kwestią, z którą twoje rozwiązanie również zadziałało. –
Cieszę się, że nie jestem jedynym, który to widział. Dzięki za obserwację! – fool4jesus
Mam do czynienia z tym samym problemem, nawet po uaktualnieniu Spring Security wersji do 3.1.4.RELEASE. – ManojP