Spring security 仅为某些特定测试加载安全性
我正在尝试进行一些集成测试来测试一些业务控制器,以及其他测试来测试安全配置Spring security 仅为某些特定测试加载安全性,spring-security,Spring Security,我正在尝试进行一些集成测试来测试一些业务控制器,以及其他测试来测试安全配置 @SpringBootTest(classes = { TestConfiguration.class, WebConfiguration.class }) @RunWith(SpringRunner.class) public abstract class BaseTest { @Before public void setup() throws Exception { this.mo
@SpringBootTest(classes = { TestConfiguration.class, WebConfiguration.class })
@RunWith(SpringRunner.class)
public abstract class BaseTest {
@Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(springSecurityFilterChain).build();
httpHeaders = new HttpHeaders();
}
}
@SpringBootTest(classes = { TestConfiguration.class, SecurityConfiguration.class, WebConfiguration.class })
public abstract class SecurityBaseTest extends BaseTest {
@Before
public void setup() throws Exception {
super.setup();
userFixtureService.addUserFixture();
addTokenToRequestHeader(httpHeaders, UserFixtureService.USER_EMAIL);
}
private void addTokenToRequestHeader(HttpHeaders headers, String username) {
tokenAuthenticationService.addTokenToResponseHeader(headers, username);
}
}
因此,我让业务控制器测试扩展BaseTest
类,安全配置测试扩展SecurityBaseTest
类
我只想为执行安全配置的测试加载安全配置,而不是为业务控制器测试加载安全配置,因为这些测试应该只执行控制器,而不是安全配置
@SpringBootTest(classes = { TestConfiguration.class, WebConfiguration.class })
@RunWith(SpringRunner.class)
public abstract class BaseTest {
@Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).addFilters(springSecurityFilterChain).build();
httpHeaders = new HttpHeaders();
}
}
@SpringBootTest(classes = { TestConfiguration.class, SecurityConfiguration.class, WebConfiguration.class })
public abstract class SecurityBaseTest extends BaseTest {
@Before
public void setup() throws Exception {
super.setup();
userFixtureService.addUserFixture();
addTokenToRequestHeader(httpHeaders, UserFixtureService.USER_EMAIL);
}
private void addTokenToRequestHeader(HttpHeaders headers, String username) {
tokenAuthenticationService.addTokenToResponseHeader(headers, username);
}
}
使用命令mvn clean install-Denv=“test”-Ddb=“h2”-Dtest=UserControllerTest-Dmaven.surefire.debug=“-Xdebug-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005-Xnoagent-Djava.compiler=NONE”运行业务控制器测试时
然后调试器显示未正确加载安全配置
但是TestCrudoOperations
方法失败,因为它返回的是403
状态,而不是预期的201
。调试器显示,UserController
controller端点根本没有被命中
public class UserControllerTest extends BaseTest {
@Test
public void testCrudOperations() throws Exception {
MvcResult mvcResult = this.mockMvc
.perform(post(RESTConstants.SLASH + UserDomainConstants.USERS)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)
.headers(httpHeaders)
.content(jacksonObjectMapper.writeValueAsString(userResource0)))
.andExpect(status().isCreated())
.andExpect(jsonPath("$.firstname").exists())
.andExpect(jsonPath("$.firstname").value(userResource0.getFirstname()))
.andExpect(jsonPath("$.lastname").value(userResource0.getLastname()))
.andExpect(jsonPath("$.email").value(userResource0.getEmail()))
.andExpect(header().string("Location", Matchers.containsString("/users/"))).andReturn();
UserResource retrievedUserResource = deserializeResource(mvcResult, UserResource.class);
assertThatUserResource(retrievedUserResource).hasEmail(userResource0.getEmail());
assertThatUserResource(retrievedUserResource)
.hasRole(retrievedUserResource.getUserRoles().iterator().next().getRole());
userResource0.setResourceId(retrievedUserResource.getResourceId());
}
}
使用命令mvn clean install-Denv=“test”-Ddb=“h2”-Dtest=UserAuthenticationTest-Dmaven.surefire.debug=“-Xdebug-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005-Xnoagent-Djava.compiler=NONE”运行安全配置测试时
然后调试器显示安全配置已正确加载
但是testUnsecuredResourceGrantsAccess方法失败,错误没有可用的“org.springframework.security.web.FilterChainProxy”类型的合格bean
public class UserAuthenticationTest extends SecurityBaseTest {
@Test
public void testUnsecuredResourceGrantsAccess() throws Exception {
this.mockMvc.perform(
post(RESTConstants.SLASH + UserDomainConstants.USERS + RESTConstants.SLASH + UserDomainConstants.LOGIN)
.accept(MediaType.APPLICATION_JSON)
)
.andDo(print())
.andExpect(status().isBadRequest())
.andReturn();
}
}
安全配置为:
@EnableWebSecurity(debug = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
public AuthenticationFromCredentialsFilter authenticationFromCredentialsFilter() throws Exception {
AuthenticationFromCredentialsFilter authenticationFromCredentialsFilter = new AuthenticationFromCredentialsFilter(new AntPathRequestMatcher("/users/login", RequestMethod.POST.name()));
authenticationFromCredentialsFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationFromCredentialsFilter;
}
@Bean
public AuthenticationFromTokenFilter authenticationFromTokenFilter() throws Exception {
AuthenticationFromTokenFilter authenticationFromTokenFilter = new AuthenticationFromTokenFilter(new NegatedRequestMatcher(new AntPathRequestMatcher("/users/login")));
authenticationFromTokenFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationFromTokenFilter;
}
@Bean
FilterRegistrationBean<AuthenticationFromTokenFilter> disableAutoRegistration(final AuthenticationFromTokenFilter filter) {
final FilterRegistrationBean<AuthenticationFromTokenFilter> registration = new FilterRegistrationBean<AuthenticationFromTokenFilter>(filter);
registration.setEnabled(false);
return registration;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors();
http
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.logout().disable();
http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(simpleCORSFilter, ChannelProcessingFilter.class);
http
.addFilterBefore(authenticationFromTokenFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
.antMatchers("/", "/error").permitAll()
.antMatchers("/users/login").permitAll()
.antMatchers("/admin/**").hasRole(UserDomainConstants.ROLE_ADMIN)
.anyRequest().authenticated();
}
}
@EnableWebSecurity(debug=true)
公共类安全配置扩展了WebSecurity配置适配器{
@豆子
公共身份验证FromCredentialsFilter身份验证FromCredentialsFilter()引发异常{
AuthenticationFromCredentialsFilter AuthenticationFromCredentialsFilter=新建AuthenticationFromCredentialsFilter(新建AntPathRequestMatcher(“/users/login”,RequestMethod.POST.name());
authenticationFromCredentialsFilter.setAuthenticationManager(authenticationManagerBean());
从CredentialsFilter返回authenticationFromCredentialsFilter;
}
@豆子
公共身份验证FromTokenFilter身份验证FromTokenFilter()引发异常{
AuthenticationFromTokenFilter AuthenticationFromTokenFilter=新的AuthenticationFromTokenFilter(新的NegatedRequestMatcher(新的AntPathRequestMatcher(“/users/login”));
authenticationFromTokenFilter.setAuthenticationManager(authenticationManagerBean());
从TokenFilter返回authenticationFromTokenFilter;
}
@豆子
FilterRegistrationBean disableAutoRegistration(来自TokenFilter筛选器的最终身份验证){
最终FilterRegistrationBean注册=新FilterRegistrationBean(过滤器);
registration.setEnabled(false);
申报登记;
}
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http.cors();
http
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.logout().disable();
http.exceptionHandling().authenticationEntryPoint(重新验证EntryPoint);
http.sessionManagement().sessionCreationPolicy(sessionCreationPolicy.STATELESS);
addFilterBefore(simpleCORSFilter,ChannelProcessingFilter.class);
http
.addFilterBefore(authenticationFromTokenFilter,UsernamePasswordAuthenticationFilter.class)
.授权请求()
.antMatchers(“/”,“/error”).permitAll()
.antMatchers(“/users/login”).permitAll()
.antMatchers(“/admin/**”).hasRole(UserDomainConstants.ROLE\u admin)
.anyRequest().authenticated();
}
}
我可以通过从@EnableWebSecurity(debug=true)中删除(debug=true)
来解决没有“org.springframework.security.web.FilterChainProxy”类型的合格bean的问题
注释。我还可以通过添加仅由非安全测试使用的安全配置来解决403
状态响应。此配置包含以下语句http.cors();http.csrf().disable().formLogin().disable().httpBasic().disable().logout().disable();http.sessionManagement().sessionCreationPolicy(sessionCreationPolicy.STATELESS);addFilterBefore(simpleCORSFilter,ChannelProcessingFilter.class)代码>