2014-09-01 9 views
5

Niedawno wprowadziliśmy ochronę CSRF do naszego projektu, który korzysta z ochrony wiosennej 3.2.Jednostki kontrolerów testujących z zabezpieczeniem CSRF włączone w Spring Security

Po włączeniu funkcji CSRF niektóre testy jednostek zawodzą, ponieważ nie ma tokena csrf na żądanie. Wprowadziłem jakąś sztuczną wartość do parametru "_csrf" i nie zadziałało.

Czy mimo to mogę uzyskać token csrf przed wysłaniem żądania (podczas testowania urządzenia)?

Odpowiedz

0

Znalazłem pracę, aby rozwiązać ten problem, tworząc niestandardową implementację CsrfTokenRepository. To zawsze wygeneruje stały token (np. "Test_csrf_token"). Możemy więc wysłać ten token jako parametr żądania (ponieważ się nie zmieni) z innymi parametrami formularza. Oto kroki, które podjąłem, aby rozwiązać mój problem.

  1. utworzyć klasę implementującą interfejs CsrfTokenRepository. Implementuj token z pewną stałą wartością tokena.

    public CsrfToken generateToken(HttpServletRequest request) { 
        return new DefaultCsrfToken(headerName, parameterName, "test_csrf_token"); 
    } 
    
    @Override 
    public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) { 
        if (token == null) { 
         HttpSession session = request.getSession(false); 
         if (session != null) { 
          session.removeAttribute(sessionAttributeName); 
         } 
        } else { 
         HttpSession session = request.getSession(); 
         session.setAttribute(sessionAttributeName, token); 
        } 
    } 
    
    @Override 
    public CsrfToken loadToken(HttpServletRequest request) { 
        HttpSession session = request.getSession(false); 
        if (session == null) { 
         return null; 
        } 
        return (CsrfToken) session.getAttribute(sessionAttributeName); 
    } 
    
  2. Dodaj odniesienie do tagu csrf w konfiguracji bezpieczeństwa.

    <http> 
        <csrf token-repository-ref="customCsrfTokenRepository" /> 
        .... 
    </http> 
    
    <beans:bean id="customCsrfTokenRepository" class="com.portal.controller.security.TestCsrfTokenRepository"></beans:bean> 
    
  3. Zmodyfikuj swoje przypadki testowe, dodając parametr żądania csrf.

    request.addParameter("_csrf", "test_csrf_token"); 
    
14

Twoja odpowiedź uiroshan jest pokonanie cel CSRF tokena: z konfiguracją będzie teraz być wartością stałą (chyba że konfiguracja jest stosowana tylko w kontekście badań, ale nie określił go) .

Prawo (i łatwiej) sposobem rozwiązania tego problemu jest:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; 

... 

@Test 
public void testLogin() throws Exception { 
    this.mockMvc.perform(post("/login") 
      .param("username", "...") 
      .param("password", "...") 
      .with(csrf())) 
     .andExpect(status().isFound()) 
     .andExpect(header().string("Location", "redirect-url-on-success-login")); 
} 

Ważną częścią jest: .with(csrf()) który doda oczekiwany _csrf parametr do zapytania.

csrf() metoda statyczna jest przez spring-security-test:

<dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-test</artifactId> 
    <version>4.2.4.RELEASE/5.0.2.RELEASE</version> 
    <scope>test</scope> 
</dependency> 

testu urządzenie będzie wymagać następujące import do niego dostęp:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; 
Powiązane problemy