测试 Spring 启动安全配置
Testing Spring Boot Security configuration
我做了一个非常简单的演示应用程序来尝试测试 Spring 启动安全性。
这是我的应用配置
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SpringBootApplication
public class DemoApplication extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityService securityService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(securityService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.httpBasic();
http.csrf().disable();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
我的 UserDetailsService 实现接受密码为 'password' 的所有用户,并向 'admin' 用户授予管理员角色。
@Service
public class SecurityService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Collection<GrantedAuthority> authorities;
if (username.equals("admin")) {
authorities = Arrays.asList(() -> "ROLE_ADMIN", () -> "ROLE_BASIC");
} else {
authorities = Arrays.asList(() -> "ROLE_BASIC");
}
return new User(username, "password", authorities);
}
}
我终于创建了一个简单的测试来检查它:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
@WebAppConfiguration
public class DemoApplicationTests {
@Autowired
private AuthenticationManager authenticationManager;
@Test
public void thatAuthManagerUsesMyService() {
Authentication auth = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken("admin", "password")
);
assertTrue(auth.isAuthenticated());
}
}
我原以为测试会通过,但我却收到了 BadCredentialsException。调试后发现测试中Spring注入的AuthenticationManager不是我配置的。在 eclipse 调试器中挖掘对象时,我看到 UserDetailsServer 是一个 InMemoryUserDetailsManager。
我还检查了 DemoApplication 中的 configure() 方法是否被调用。我做错了什么?
每个 WebSecurityConfigurerAdapter api reference 对于 authenticationManagerBean()
Override this method to expose the
AuthenticationManager from configure(AuthenticationManagerBuilder) to
be exposed as a Bean.
所以只需在您的 WebSecurityConfigurerAdapter 中覆盖 authenticationManagerBean()
并将其公开为带有 @Bean
的 bean。
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
我做了一个非常简单的演示应用程序来尝试测试 Spring 启动安全性。
这是我的应用配置
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SpringBootApplication
public class DemoApplication extends WebSecurityConfigurerAdapter {
@Autowired
private SecurityService securityService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(securityService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.httpBasic();
http.csrf().disable();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
我的 UserDetailsService 实现接受密码为 'password' 的所有用户,并向 'admin' 用户授予管理员角色。
@Service
public class SecurityService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Collection<GrantedAuthority> authorities;
if (username.equals("admin")) {
authorities = Arrays.asList(() -> "ROLE_ADMIN", () -> "ROLE_BASIC");
} else {
authorities = Arrays.asList(() -> "ROLE_BASIC");
}
return new User(username, "password", authorities);
}
}
我终于创建了一个简单的测试来检查它:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
@WebAppConfiguration
public class DemoApplicationTests {
@Autowired
private AuthenticationManager authenticationManager;
@Test
public void thatAuthManagerUsesMyService() {
Authentication auth = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken("admin", "password")
);
assertTrue(auth.isAuthenticated());
}
}
我原以为测试会通过,但我却收到了 BadCredentialsException。调试后发现测试中Spring注入的AuthenticationManager不是我配置的。在 eclipse 调试器中挖掘对象时,我看到 UserDetailsServer 是一个 InMemoryUserDetailsManager。
我还检查了 DemoApplication 中的 configure() 方法是否被调用。我做错了什么?
每个 WebSecurityConfigurerAdapter api reference 对于 authenticationManagerBean()
Override this method to expose the AuthenticationManager from configure(AuthenticationManagerBuilder) to be exposed as a Bean.
所以只需在您的 WebSecurityConfigurerAdapter 中覆盖 authenticationManagerBean()
并将其公开为带有 @Bean
的 bean。
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}