2015-05-04 57 views
2

我剛剛發現了新的Spring Security 4測試註釋@WithMockUser,但是我不能讓它爲我的Selenium測試工作。 問題是,這個註釋創建了一個模擬SecurityContext,但由HttpSessionSecurityContextRepository創建了一個新模型,因爲Selenium基於真實瀏覽器運行測試。 我可以告訴Spring使用模擬SecurityContext作爲下一個會話安全上下文嗎?Spring Security @WithMockUser for Selenium test

謝謝!

回答

1

我發現的方式與測試類路徑中一個新的過濾器進行模擬驗證用戶的身份:

@Component 
public class MockUserFilter extends GenericFilterBean { 

    @Autowired 
    private UserDetailsService userDetailsService; 

    private SecurityContext securityContext; 

    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { 
     HttpServletRequest request = (HttpServletRequest) servletRequest; 
     HttpServletResponse response = (HttpServletResponse) servletResponse; 
     if (securityContext != null) { 
      SecurityContextRepository securityContextRepository = WebTestUtils.getSecurityContextRepository(request); 

      HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(request, response); 
      securityContextRepository.loadContext(requestResponseHolder); 

      request = requestResponseHolder.getRequest(); 
      response = requestResponseHolder.getResponse(); 

      securityContextRepository.saveContext(securityContext, request, response); 

      securityContext = null; 
     } 
     chain.doFilter(request, response); 
    } 

    public void authenticateNextRequestAs(String username) { 
     UserDetails principal = userDetailsService.loadUserByUsername(username); 
     Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities()); 
     securityContext = SecurityContextHolder.createEmptyContext(); 
     securityContext.setAuthentication(authentication); 
    } 
} 

它是由SecurityMockMvcRequestPostProcessorsWithUserDetailsSecurityContextFactory啓發。

我不能使用@WithUserDetails註釋,因爲我跑黃瓜測試,但用此過濾器,我可以在同一行嘲笑的驗證下一個請求:因爲同時接受的答案幫助testSecurityFilter.authenticateNextRequestAs("username");

+0

你有完整的例子嗎? –

0

我加入這個答案我在形成一個解決方案,我不得不做出一些改變,讓這個工作。這個答案還幫我得到它的工作:https://stackoverflow.com/a/8336233/2688076

這裏是我的MockUserFilter:

 @Component("MockUserFilter") 
     public class MockUserFilter extends GenericFilterBean { 
      @Autowired 
      private UserDetailService userDetailService; 

      private SecurityContext securityContext; 

      @Autowired 
      private AuthenticationProvider authenticationProvider; 

      public void setUserDetailService(UserDetailService userDetailService) { 
       this.userDetailService = userDetailService; 
      } 
      @Override 
      public void doFilter(ServletRequest request, ServletResponse response, 
        FilterChain chain) throws IOException, ServletException { 
       HttpServletRequest servletRequest = (HttpServletRequest) request; 
       HttpServletResponse servletResponse = (HttpServletResponse) response; 

       if (securityContext != null) { 
        SecurityContextRepository securityContextRepository = WebTestUtils.getSecurityContextRepository(servletRequest); 
        HttpRequestResponseHolder requestResponseHolder = new HttpRequestResponseHolder(servletRequest, servletResponse); 
        securityContextRepository.loadContext(requestResponseHolder); 
        servletRequest = requestResponseHolder.getRequest(); 
        servletResponse = requestResponseHolder.getResponse(); 
        securityContextRepository.saveContext(securityContext, servletRequest, servletResponse); 
        securityContext = null; 
       } 

       chain.doFilter(request, response); 
      } 

      public void authenticateNextRequestAs(String username, ServletRequest request) { 
       UserDetails principal = userDetailService.loadUserByUsername(username); 
       Authentication authentication = new UsernamePasswordAuthenticationToken(principal, principal.getPassword(), principal.getAuthorities()); 
       securityContext = SecurityContextHolder.createEmptyContext(); 
       securityContext.setAuthentication(authentication); 
       SecurityContextHolder.getContext().setAuthentication(authentication); 

       HttpSession session = ((HttpServletRequest) request).getSession(true); 
       session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext); 
      } 
     } 

除了這個我也不得不從過濾器鏈中刪除我的casAuthenticationFilter得到這個工作。我使用一個屬性值來啓用/禁用它。

我對Spring和Spring安全性比較陌生,所以對這個解決方案的任何評論都是值得歡迎的。我不確定這個解決方案有多「好」或「壞」。

有一點需要記住的是,這是一個在安全環境下進行本地測試或測試的解決方案,而不是您希望在開發環境中使用的解決方案。