我有一个spring boot (版本1.5.9.RELEASE)应用程序,它使用spring-session在Redis上存储会话。它还使用spring-security对用户进行身份验证。在运行应用程序时,在成功登录之后,安全上下文包含Authentication对象。但是在运行单元测试时,我得到了这个错误消息Authentication should not be null。要重现的代码如下:
@SpringBootApplication
public class DemoRedisDataSessionApplication {
@Configuration
@EnableWebSecurity
@EnableRedisHttpSession(redisNamespace = "demo-redis-spring-session")
public static class AppConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("0000").roles("USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and()
.authorizeRequests().anyRequest().fullyAuthenticated();
}
}
@RestController
public static class AppController {
@GetMapping("/secured")
public String secured() {
return "secured";
}
}
public static void main(String[] args) {
SpringApplication.run(DemoRedisDataSessionApplication.class, args);
}
}这是application.properties
spring.session.store-type=redis下面是失败的测试
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class DemoRedisDataSessionApplicationTests {
@Autowired
private MockMvc mockMvc;
@Test
public void testUserShouldBeAuthenticated() throws Exception {
mockMvc.perform(formLogin().user("user").password("0000"))
.andExpect(status().is3xxRedirection())
.andExpect(authenticated());
}
}测试失败的错误消息:
java.lang.AssertionError: Authentication should not be null
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:35)
at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:65)
at org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers$AuthenticatedMatcher.match(SecurityMockMvcResultMatchers.java:98)特别是在类HttpSessionSecurityContextRepository第110行中,会话似乎是空的,但我不明白为什么。
我希望用户在成功登录后进行身份验证并填充SecurityContext。你有什么办法来解决这个问题吗?
发布于 2018-01-11 12:02:32
更新:
首先,您需要指示您的身份验证提供者(在本例中,它是默认的DaoAuthenticationProvider)返回哪种类型的Authentication对象。例如,您可以将httpBasic()添加到自定义WebSecurityConfigurerAdapter中的configure(HttpSecurity http)方法中。本质上,httpBasic()会将您的用户名和密码转换为一个UsernamePasswordAuthenticationToken对象,以便您的DaoAuthenticationProvider可以使用它进行身份验证。
此外,您还需要为您的登录url执行permitAll。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and()
.authorizeRequests()
.antMatchers("/login/**").permitAll()
.anyRequest().fullyAuthenticated()
.and().httpBasic();
}关于单元测试,这个问题是由于您没有在mockMvc对象中引入spring安全性。由于您实际上是spring-boot,我将给您一个使用spring-boot-test的示例解决方案:
@RunWith(SpringRunner.class)
@SpringBootTest
@WebAppConfiguration
public class DemoRedisDataSessionApplicationTests {
@Autowired
WebApplicationContext wac;
private MockMvc mockMvc;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(wac)
.apply(springSecurity())
.build();
}
@Test
public void testUserShouldBeAuthenticated() throws Exception {
mockMvc.perform(formLogin().user("user").password("0000"))
.andExpect(status().is3xxRedirection())
.andExpect(authenticated());
}
}注意:上面代码中的springSecurity()来自import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity。
https://stackoverflow.com/questions/48189039
复制相似问题