Spring Security on Wildfly: błąd podczas wykonywania łańcucha filtrów

194

Próbuję zintegrować rozszerzenie Spring Security SAML z Spring Boot .

W tej sprawie opracowałem kompletną aplikację przykładową. Jego kod źródłowy jest dostępny na GitHub:

Uruchamiając go jako aplikację Spring Boot (działającą na wbudowanym serwerze aplikacji SDK), WebApp działa dobrze.

Niestety ten sam proces AuthN w ogóle nie działa w Undertow / WildFly .

Według dzienników IdP faktycznie wykonuje proces AuthN : instrukcje mojej niestandardowej UserDetailsimplementacji są poprawnie wykonywane. Pomimo wykonania, Spring nie konfiguruje i nie utrzymuje uprawnień dla bieżącego użytkownika.

@Component
public class SAMLUserDetailsServiceImpl implements SAMLUserDetailsService {

    // Logger
    private static final Logger LOG = LoggerFactory.getLogger(SAMLUserDetailsServiceImpl.class);

    @Override
    public Object loadUserBySAML(SAMLCredential credential)
            throws UsernameNotFoundException, SSOUserAccountNotExistsException {
        String userID = credential.getNameID().getValue();
        if (userID.compareTo("[email protected]") != 0) {     // We're simulating the data access.
            LOG.warn("SSO User Account not found into the system");
            throw new SSOUserAccountNotExistsException("SSO User Account not found into the system", userID);
        }
        LOG.info(userID + " is logged in");
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
        authorities.add(authority);
        ExtUser userDetails = new ExtUser(userID, "password", true, true, true,
                true, authorities, "John", "Doe");
        return userDetails;
    }
}

Podczas debugowania dowiedziałem się, że problem zależy od FilterChainProxyklasy. W czasie wykonywania atrybut FILTER_APPLIEDz ServletRequestma zerową wartość, tym samym Wiosna czyści SecurityContextHolder.

private final static String FILTER_APPLIED = FilterChainProxy.class.getName().concat(".APPLIED");

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
    if (clearContext) {
        try {
            request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
            doFilterInternal(request, response, chain);
        } finally {
            SecurityContextHolder.clearContext();
            request.removeAttribute(FILTER_APPLIED);
        }
    } else {
        doFilterInternal(request, response, chain);
    }
}

W VMware vFabric tc Sever i Tomcat wszystko działa całkowicie dobrze. Czy masz pomysł na rozwiązanie tego problemu?

vdenotaris
źródło
2
W większości sytuacji SecurityContextHoldernależy to wyczyścić po zgłoszeniu. Jedynym celem tego kodu jest przypadek zastosowania łańcucha filtrów więcej niż raz podczas tego samego żądania (w takim przypadku tylko oryginalny łańcuch powinien wyczyścić kontekst). Więc nie sądzę, żeby to był problem.
Shaun the Sheep
2
BTW, to zachowanie za każdym razem unieważnia proces logowania. Czy istnieje sposób, aby to naprawić, na przykład poprzez odpowiednią konfigurację oprogramowania AS?
vdenotaris,
1
Nie jestem pewien, co przez to rozumiesz. Jakie zachowanie i jak unieważnia logowanie? Czyszczenie kontekstu po zakończeniu obsługi żądania przez wątek jest normalnym zachowaniem - konieczne jest zapobieganie wyciekaniu danych lokalnych wątków z powrotem do puli wątków. W tym momencie kontekst powinien być zwykle buforowany w sesji użytkownika. Dlatego nie powinno to unieważniać logowania.
Shaun the Sheep
2
Jak opisano powyżej, po rejestracji jednokrotnej serwer aplikacji usuwa dane sesji i dane uwierzytelniania. Dzieje się tak tylko w przypadku Wildfly: ten sam kod działa poprawnie z Tomcat.
vdenotaris,
11
SecurityContextHolder.clearContext()nie usuwa danych sesji. Usuwa ThreadLocalprzechowywanie kontekstu przed zwolnieniem wątku z powrotem do puli wątków. Chodzi mi o to, że zawsze powinno się to zdarzyć na końcu żądania, więc to, co widzisz, jest normalne i prawdopodobnie nie będzie przyczyną twojego problemu.
Shaun the Sheep

Odpowiedzi:

7

Badanie problemu Zauważyłem, że w żądaniu uwierzytelnienia jest trochę bałaganu z plikami cookie i odnośnikami.

Obecnie uwierzytelnianie typu wildfly będzie działać, jeśli zmienisz kontekst aplikacji WWW na kontekst główny:

 <server name="default-server" default-host="webapp">
     <http-listener name="default" socket-binding="http"/>
     <host name="default-host" alias="localhost" default-web-module="sso.war"/>
 </server>

Po ponownym uruchomieniu wildfly i wyczyszczeniu plików cookie wszystko powinno działać zgodnie z oczekiwaniami

nesteant
źródło
fajne rozwiązanie, jeśli jesteś znany z WildFly i JBOSS, czy możesz rzucić okiem na to pytanie stackoverflow.com/questions/59006162/...
ZINE Mahmoud