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)