我可以使用一些帮助来测试我的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。
答案 0 :(得分:0)
模拟Filter接口以注入springSecurityFilterChain bean是错误的。
你想要的是注入一个带有至少一个身份验证过滤器的过滤器链,例如: UsernamePasswordAuthenticationFilter CasAuthenticationFilter BasicAuthenticationFilter一样。 阅读this spring安全过滤器链指南,了解要为您的目的注入哪些过滤器。
现在mockito正在springSecurityFilterChain上设置一个过滤器,该过滤器允许所有网址,但不提供预期的过滤行为。
修复可能就像在Test类中包含对正确的应用程序上下文和TestContext的引用一样简单,取决于您如何为应用程序的其余部分定义上下文。我怀疑过滤链豆也可用于自动接线。
<强>更新强>
告诉spring在这里加载TokenContext和AuthenticationStatelessContext:
@ContextConfiguration(classes = TestContext.class)
删除任何代码以在TestContext中定义安全过滤器链bean