MockMvc使用模拟会话绕过安全性

时间:2016-05-10 19:47:53

标签: java spring junit spring-security spring-boot

我正在一套微服务中开发一个spring-boot微服务。使用两个功能保护服务端点:@PreAuthorize注释和提供额外无状态身份验证的自定义GenericFilterBean。

有些人使用MockMvc首先发布到登录URL,然后从指定的端点获取。这对我来说是个问题,因为登录是由不同的微服务执行的。

我做了不同的尝试而没有完全理解,可以概括为:

  1. 通过其他微服务登录以获取带有Cookie设置的会话
  2. 模拟会话以使用假cookie
  3. 禁用安全和自定义过滤器
  4. MockMvc不允许调用外部网址来执行登录,因此第一个被排除在外。模拟会话并没有给我一个设置cookie的方法 - 我只在响应对象上看到addCookie。禁用自定义过滤器导致没有任何事情发生(也许我做错了)。

    在我看来,正确的测试方法是拥有一个有效的模拟会话并允许安全性保持不变。我很难过如何继续。

    spring-boot父pom是:spring-cloud-starter-parent - Brixton.M4

    如何测试单个微服务并绕过安全性?

1 个答案:

答案 0 :(得分:5)

我前一段时间遇到过类似的问题,我花了一些时间才找到答案,不确定这是否能解决您的问题,但我可以设法使用mockMvc使用以下方法进行身份验证

创建一个负责身份验证的类。它可能是这样的

public class Auth {  

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private FilterChainProxy springSecurityFilter;

    protected MockMvc mockMvc;
    protected MockHttpSession session;

    public void setup() throws Exception{
        this.session = new MockHttpSession();
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac)
                .addFilters(springSecurityFilter)
                .build();
    }

    protected void setAuthentication(String user, String password, MockHttpSession session){
        Authentication authentication = new UsernamePasswordAuthenticationToken(user, password);
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);

        session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,securityContext);
    }
}

现在您可以简单地扩展此类并使用方法setAuthenticatio登录并执行测试。例如

public class myTest extends Auth {
     @Test
     public void test{ 
         setAuthentication('user', 'password', session);
         // perform you tests using mockmvc
         // mockMvc.perform(post('url')...

     }

}