2014-10-01 25 views
8

Obecnie mamy problem z roztworu Wiosna CSRF dla naszej spuścizny App ponieważ realizacja CSRF zmienia zachowanie domyślne Wiosna zabezpieczeń konfiguracji zabezpieczeń wiosennym sis następujący:Wiosna CSRF override „POST” zachowanie wylogowania w XML bezpieczeństwo config

<http pattern=""> 
... 
<logout 
       logout-url="/logout" 
       delete-cookies="..." 
       success-handler-ref="logoutSuccessHandler" 
       /> 
<csrf/> 
</http> 

org.springframework.security.config.annotation.web.configurers.LogoutConfigurer Wylogowanie configurer. Zgodnie z dokumentacją Spring:

Dodanie CSRF zaktualizuje LogoutFilter tak, aby korzystał tylko z HTTP POST. Ten numer zapewnia, że ​​wylogowanie wymaga tokena CSRF, a złośliwy użytkownik nie może wymusić wylogowania użytkowników.

kod sprawia, że ​​ta zmiana jest następująca:

private RequestMatcher getLogoutRequestMatcher(H http) { 
     if(logoutRequestMatcher != null) { 
      return logoutRequestMatcher; 
     } 
     if(http.getConfigurer(CsrfConfigurer.class) != null) { 
      this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); 
     } else { 
      this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl); 
     } 
     return this.logoutRequestMatcher; 
    } 

Ogólnie o ochronę CSRF takie zachowanie ma sens. Ale co do mnie, to bardzo dziwne, że ta implementacja nie jest elastyczna (dlaczego używasz hardcode do prawdziwych implementacji i nie zależy od autoworów?).

Problem polega na tym, że nasza aplikacja została zbudowana w taki sposób, że przed regularnym wylogowaniem wiosennym wykonano dodatkowe czyszczenie w kontrolerach sprężynowych. Głównie została zaimplementowana funkcja Switch User, ale w niestandardowy sposób. Tak więc zmiana łącza wylogowania w celu wykonania POST nie jest opcją, ponieważ głównie czyszczenie odbywa się na niestandardowym kontrolerze.

Wydaje się, aby użyć określonego podejścia jest tylko jednym z możliwych rozwiązań:

@RequestMapping(value = "/logout", method = RequestMethod.GET) //or it can be a post 
    public String logout() { 
// 1. Perform Clean up 
// 2. Decide whether to logout or redirect to other page 
// 3. Perform redirect based on decision 
} 

// Jeśli zdecydował się wylogować ten trafi do tej metody Kontroler:

@RequestMapping(value = "csrflogout", method = RequestMethod.GET) 
    public void csrfLogout(){ 
//1 Create manual post request 
//2. Copy session information 
//3. Perform Post to logout URL that is specified in security xml 
    } 

Generalnie podejście nie jest dobre z perspektywy jakości kodu. Tak, istnieją dwa pytania:

  1. Jaki jest powód, aby dokonać takiego ścisłego wdrożenia na wiosnę i nie dostarczają żadnych widocznych możliwość, aby go zastąpić (w szczególności I, pod warunkiem przykład kodu, jak to utworzone)?
  2. Dobra alternatywa dla naprawienia wspomnianego problemu.
+1

Dlaczego w ogóle korzystasz z kontrolera? Ogólnie rzecz biorąc, lepiej jest umieścić taką logikę w [LogoutHandler] (http://docs.spring.io/autorepo/docs/spring-security/current/apidocs/org/springframework/security/web/authentication/logout /LogoutHandler.html) w taki sposób, aby ładnie zintegrować się z programem Spring Security, zamiast próbować go rozwiązać w kontrolerze. Również POST będzie działał, jeśli po oczyszczeniu w przód (nie przekierowaniu!) Do adresu URL wylogowania. –

+0

Również nie ma nic, co uniemożliwiłoby skonfigurowanie wylogowania do obsługi GET bez względu na ochronę CSFR, jest to tylko domyślne, jeśli nadpisujesz to po prostu zrób. –

+1

Czy możesz dodać więcej szczegółów, jak skonfigurować wylogowanie, które ma być obsługiwane w usłudze GET z obsługą CSRF (wystarczy opublikować jako odpowiedź na ten wpis)? – user1459144

Odpowiedz

8

Zachowanie, które opisujesz, jest zachowaniem, jeśli nie jawnie skonfigurujesz obsługę wylogowania, ale tylko ją włączysz, to zostanie ona jawnie skonfigurowana, aby użyć tej konfiguracji.

Jest to również documented w przewodniku referencyjnym.

Jednak prawdziwym rozwiązaniem jest to, że nie powinieneś używać kontrolera do dodatkowej funkcji wylogowania, ale zamiast tego użyj LogoutHandler. To dobrze się sprawdzi z programem Spring Security i nie trzeba przekierowywać/przekazywać do różnych adresów URL.

+0

Czy znasz prosty sposób na zrobienie tego w konfiguracji XML? – user1459144

+0

Opublikowany kod jest związany z konfiguracją opartą na języku Java NOT xml. W XML csfr jest domyślnie wyłączone i nie jest włączone. 'LogoutConfigurer' jest używany tylko wtedy, gdy używasz konfiguracji opartej na Javie NIE dla konfiguracji XML. Powiedziałbym więc, że twoje pytanie jest mylące. W przypadku XML obawiam się, że musisz ręcznie skonfigurować 'LogoutFilter' zamiast używać przestrzeni nazw, ponieważ' LogoutBeanDefinitionParser' (który jest używany!) Zawsze zmienia się na POST, gdy włączone jest csfr. –

+0

Przepraszam, że nie wskazałem, że używana jest konfiguracja XML w Spring security. LogoutConfigurer jest również używany w konfiguracji XML. Przyjrzę się podejściu do ręcznego skonfigurowania filtru wylogowania – user1459144

4

Zasadniczo główna złożoność polegała na nadpisywaniu kontekstu logoutFilter w źródle Spring Security XML w celu pracy z domyślną implementacją org.springframework.security.web.util.matcher.AntPathRequestMatcher (która obsługuje żądania "GET", a nie "POST"). Aby to zrobić kilka ziaren dodano kontekście bezpieczeństwa xml:

<bean id="logoutAntPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> 
     <constructor-arg value="logout" /> 
    </bean> 

i filtr wylogowania sama:

<bean id="logoutFilter" 
    class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
    <constructor-arg name="logoutSuccessHandler" ref="logoutSuccessHandler"/> 
    <constructor-arg name="handlers"> 
     <list> 
      <ref bean="securityContextLogoutHandler" /> 
      <ref bean="cookieClearingLogoutHandler" /> 
      <ref bean="csrfLogoutHandler" /> 
     </list> 
    </constructor-arg> 
    <property name="filterProcessesUrl" value="/logout"/> 
    <property name="logoutRequestMatcher" ref="logoutAntPathRequestMatcher"/> 
</bean> 
0

Widziałem ten sam błąd po aktualizacji Internet Explorer 11. CsrfConfigurer.class nie ma wartości null i oczekuje się, że post wyloguje się.

if(http.getConfigurer(CsrfConfigurer.class) != null) { 
      this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST"); 
     } else { 
      this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl); 
     } 

I rozwiązał problem pominięciem logoutfilter i wstawić nowy filtr skoczyć do bezpieczeństwa

przykład przedstawiono poniżej.

<beans:bean id="logoutAntPathRequestMatcher" class="org.springframework.security.web.util.matcher.AntPathRequestMatcher"> 
      <beans:constructor-arg value="/logout"/> 
     </beans:bean> 

     <beans:bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"> 

     </beans:bean> 


     <beans:bean id="cookieClearingLogoutHandler" class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler"> 
      <beans:constructor-arg value="JSESSIONID"/> 
     </beans:bean> 

     <beans:bean id="logoutFilter" 
       class="org.springframework.security.web.authentication.logout.LogoutFilter"> 
      <beans:constructor-arg name="logoutSuccessUrl" value="/login"/> 
      <beans:constructor-arg name="handlers"> 
       <beans:list> 
        <beans:ref bean="securityContextLogoutHandler" /> 
        <beans:ref bean="cookieClearingLogoutHandler" /> 
       </beans:list> 
      </beans:constructor-arg> 
      <beans:property name="filterProcessesUrl" value="/logout"/> 
      <beans:property name="logoutRequestMatcher" ref="logoutAntPathRequestMatcher"/> 
     </beans:bean> 


<http> 
... 
<sec:custom-filter ref="logoutFilter" after="LOGOUT_FILTER"/> 
... 
</http> 
Powiązane problemy