2013-06-14 7 views
7

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!)

Odpowiedz

4

Nie udało mi się uzyskać ostatecznego oświadczenia o tym, ale problem wydaje się być z Spring Security 3.1.1 nie gra dobrze z Spring SAML lub faktycznie jakiejkolwiek implementacji używa tego samego zagnieżdżonego FilterChainProxys. Wygląda na to, że FilterChainProxy został całkowicie przepisany na wersję 3.1.1. Kiedy przyjrzałem się najnowszemu wydaniu (3.1.4), zauważyłem, że istnieje check w klauzuli finally, która tylko czyści SecurityContextHolder ("SEC-1950") JEŻELI jest to pierwsze wywołanie filtra.

W ten sposób aktualizacja zabezpieczenia sprężynowego do wersji 3.1.4 rozwiązała problem.

+0

Dziękujemy za opublikowanie rozwiązania. Zmierzyłem się z tą samą kwestią, z którą twoje rozwiązanie również zadziałało. –

+0

Cieszę się, że nie jestem jedynym, który to widział. Dzięki za obserwację! – fool4jesus

+0

Mam do czynienia z tym samym problemem, nawet po uaktualnieniu Spring Security wersji do 3.1.4.RELEASE. – ManojP

Powiązane problemy