2013-06-14 5 views
7

Ich versuche, ein Problem mit Spring Security und SAML herauszufinden. Wir versuchen, Spring Security (spring-security-core-3.1.1.RELEASE.jar) und SAML (spring-security-saml2-core-1.0.0-RC1-SNAPSHOT.jar) zu verwenden, um unser Produkt zu modifizieren SAML SP. EDIT: Hier ist der (ich denke!) Relevante Abschnitt meines sicherheitsrelevanten Kontext-XML. Wie Sie sehen können, ist es fast identisch mit this sample XML.Spring Security und geschachtelte FilterChainProxy schreiben SAML-Dienstanbieter

Das Symptom ist, dass sofort nach der Authentifizierung mit dem IDP die Seite meines SP korrekt angezeigt wird; Durch das Ändern der URL (z. B. durch Klicken auf einen Link) werde ich jedoch sofort zum IDP zurückgeleitet. Ich denke, ich habe herausgefunden, warum, aber ich weiß nicht, warum das nicht immer der Fall ist.

Mein Verständnis von Spring Security ist, dass Berechtigungsprüfung alle um den SecurityContextHolder basiert. Nämlich, legen Sie ein Authentifizierungsobjekt auf den Halter, und alles wird von auth überprüft. Dann ist SecurityContextPersistenceFilter dafür zuständig, das Sitzungs-Repository so zu verwalten, dass es übereinstimmt.

So, wie ich durch den Code Spring Security verfolgen, ich sehe SecurityContextPersistenceFilter mit dem folgenden Code:

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()); 
    .... 
} 

So weit, so gut. Dann sehe ich FilterChainProxy und finden:

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 
    } 
} 

Das noch in Ordnung zu sein scheint. Da FilterChainProxy nur einmal aufgerufen werden sollte, ist es an der Basis aller Spring Security-Filter kein Problem, den SecurityContextHolder zu diesem Zeitpunkt zu löschen.

ABER das ist nicht, was passiert. Was eigentlich passiert, ist der clearContext in FilterChainProxy heißt BEFORE SecurityContextPersistenceFilter bekommt eine Chance, es aus dem Kontext in contextAfterChainExecution zu lesen. Der Grund dafür ist, dass FilterChainProxy tatsächlich zweimal in der Aufrufkette auftritt. Ich weiß das, weil ich in FilterChainProxy.doFilter einen Haltepunkt gesetzt habe und es zweimal aufgerufen wird. Das erste Mal, dass es aufgerufen wird, hat es eine andere Instanz von FilterChainProxy in seinem FilterChain. Hier ist der Stapel der Filter durch FilterChainProxy der getFilters Methode zurückgegeben:

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 

Mit dieser Kette von Filtern, ich verstehe nicht, wie SecurityContextPersistenceFilter kann jemals funktionieren: es scheint, wie die SecurityContextHolder wird immer gelöscht werden, bevor es eine Chance bekommt es bestehen bleiben.

Ist hier etwas offensichtlich falsch? Bin ich Missverständnis etwas in Spring Security (sehr möglich!)

Antwort

4

Ich war nicht in der Lage, eine endgültige Aussage davon zu bekommen, aber das Problem scheint mit Spring Security 3.1.1 nicht gut mit Spring SAML oder tatsächlich jede Implementierung das verwendet die gleiche Art von verschachtelten FilterChainProxys. Es scheint, dass FilterChainProxy für 3.1.1 komplett neu geschrieben wurde. Als ich mir die neueste Version (3.1.4) angeschaut habe, ist mir aufgefallen, dass es in der finally-Klausel eine Überprüfung gibt, die nur den SecurityContextHolder ("SEC-1950") löscht, WENN es der erste Aufruf des Filters ist.

Die Aktualisierung der Federsicherheit auf 3.1.4 löste das Problem.

+0

Vielen Dank für die Buchung der Lösung. Ich stand vor dem gleichen Problem, dass Ihre Lösung auch für mich funktioniert hat. –

+0

Freut mich zu hören, dass ich nicht der einzige bin, der es gesehen hat. Danke für das Nachschlagen! – fool4jesus

+0

Ich bin mit demselben Problem konfrontiert, selbst nach der Aktualisierung der Federsicherheitsversion auf 3.1.4.RELEASE. – ManojP