在REST端点上测试身份验证

时间:2016-11-18 15:00:15

标签: java spring spring-mvc testing

我可以使用一些帮助来测试我的Spring REST端点的身份验证(使用spring身份验证)。 我已经定义了一些需要使用以下注释进行身份验证的端点@PreAuthorize(" isAuthenticated()")。 这似乎有效,因为当我启动网络服务器并转到URL时,我要求进行身份验证,之后我会得到正确的结果。

我的测试遇到了麻烦。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestContext.class)
@WebAppConfiguration
public class ControllerTest {

    @Autowired
    private WebApplicationContext context;

    private MockMvc mvc;

    @Before
    public void setup() {
        mvc = MockMvcBuilders
                .webAppContextSetup(context)
                .apply(springSecurity())
                .build();
    }

    @Test
    public void testGetMethod() throws Exception {
        mvc
            .perform(get("/a-valid-url")
                        .accept(MediaType.APPLICATION_JSON))
            .andDo(print())
            .andExpect(status().isUnauthorized());
    }

}

TestContext类在控制器中包含一些被模拟的自动装配类,如下所示:

@Configuration
public class TestContext {

    @Bean
    public ClassToMock autowiredClass() {
        return Mockito.mock(ClassToMock.class);
    }

}

当像这样运行时,我收到以下错误: java.lang.IllegalStateException:springSecurityFilterChain不能为null。确保使用名为springSecurityFilterChain的Bean实现Filter,或者注入要使用的Filter。

到目前为止我发现的唯一解决方案是在TestContext类中添加一个springSecurityFilterChain bean,如下所示:

@Bean
public Filter springSecurityFilterChain() {
    return Mockito.mock(Filter.class);
}

然而,即使我使用未在控制器中定义的URL,我总是得到Status = 200。

如果有人能指出我正确的方向,我将不胜感激!

编辑:项目的部分配置。

的web.xml

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

该项目有另一个项目作为依赖项,其中包含TokenContext和AuthenticationStatelessContext配置XML文件。

TokenContext.xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:security="http://www.springframework.org/schema/security"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
                            http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                            http://www.springframework.org/schema/security 
                            http://www.springframework.org/schema/security/spring-security-4.0.xsd 
                            http://www.springframework.org/schema/context 
                            http://www.springframework.org/schema/context/spring-context-4.1.xsd" >

    <context:component-scan base-package="com.example.auth.service" resource-pattern="TokenServiceImpl.class"/>
    <context:component-scan base-package="com.example.auth.service" resource-pattern="ActorRolServiceImpl.class"/>
</beans>

AuthenticationStatelessContext.xml定义以下spring bean:DefaultMethodSecurityExpressionHandler,PreAuthenticatedAuthenticationProvider和UserDetailsByNameServiceWrapper。

更新 创建了一个名为TestContext2的类:

@Configuration
@ImportResource({
    "classpath:**/AuthenticationStatelessContext.xml",
    "classpath:**/TokenContext.xml"})
public class TestContext2 {

}

并将该课程添加到测试中

@ContextConfiguration(classes = {TestContext.class, TestContext2.class})

这是因为spring不允许在@ContextConfiguration注释中同时加载类和xml文件。

当我尝试运行测试时,我仍然会收到以下错误: java.lang.IllegalStateException:springSecurityFilterChain不能为null。

PS:使用的springframework版本是4.1.3,spring-security版本是4.0.4。

1 个答案:

答案 0 :(得分:0)

模拟Filter接口以注入springSecurityFilterChain bean是错误的。

你想要的是注入一个带有至少一个身份验证过滤器的过滤器链,例如: UsernamePasswordAuthenticationFilter CasAuthenticationFilter BasicAuthenticationFilter一样。 阅读this spring安全过滤器链指南,了解要为您的目的注入哪些过滤器。

现在mockito正在springSecurityFilterChain上设置一个过滤器,该过滤器允许所有网址,但不提供预期的过滤行为。

修复可能就像在Test类中包含对正确的应用程序上下文和TestContext的引用一样简单,取决于您如何为应用程序的其余部分定义上下文。我怀疑过滤链豆也可用于自动接线。

<强>更新

告诉spring在这里加载TokenContext和AuthenticationStatelessContext:

@ContextConfiguration(classes = TestContext.class)

删除任何代码以在TestContext中定义安全过滤器链bean