2015-05-04 56 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安全性比较陌生,所以对这个解决方案的任何评论都是值得欢迎的。我不确定这个解决方案有多“好”或“坏”。

有一点需要记住的是,这是一个在安全环境下进行本地测试或测试的解决方案,而不是您希望在开发环境中使用的解决方案。