用于 Selenium 测试的 Spring Security @WithMockUser
Posted
技术标签:
【中文标题】用于 Selenium 测试的 Spring Security @WithMockUser【英文标题】:Spring Security @WithMockUser for Selenium test 【发布时间】:2015-07-14 02:41:29 【问题描述】:我刚刚发现了新的 Spring Security 4 测试注释 @WithMockUser
,但我无法让它用于我的 Selenium 测试。
问题是,这个注解创建了一个模拟 SecurityContext
,但是一个新的是由 HttpSessionSecurityContextRepository
创建的,因为 Selenium 基于一个真实的浏览器运行测试。
我能否以某种方式告诉 Spring 使用模拟 SecurityContext
作为下一个会话安全上下文?
谢谢!
【问题讨论】:
【参考方案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);
它的灵感来自SecurityMockMvcRequestPostProcessors
和WithUserDetailsSecurityContextFactory
。
我无法使用 @WithUserDetails
注释,因为我运行 Cucumber 测试,但使用此过滤器,我可以在一行中模拟下一个请求的身份验证:testSecurityFilter.authenticateNextRequestAs("username");
【讨论】:
你有完整的例子吗?【参考方案2】:我添加此答案是因为虽然接受的答案帮助我形成了解决方案,但我必须进行一些更改才能使其正常工作。这个答案也帮助我让它工作:https://***.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 安全性比较陌生,因此欢迎使用此解决方案的任何 cmets。我不确定这个解决方案有多“好”或“坏”。
要记住的一点是,这是一种用于本地测试或在安全环境中进行测试的解决方案,而不是您在开发环境中想要的解决方案。
【讨论】:
以上是关于用于 Selenium 测试的 Spring Security @WithMockUser的主要内容,如果未能解决你的问题,请参考以下文章