Spring OAuth 和引导集成测试 [英] Spring OAuth and Boot Integration Test

查看:33
本文介绍了Spring OAuth 和引导集成测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 OAuth 资源服务器配置的 Web 应用程序中再次运行 Spring Boot 集成测试的最佳方法是什么.

What is the best way to run Spring Boot integration tests agains a OAuth Resource server configured web application.

我可以想到两种理论方法:

I can think of two theoretical approaches:

  1. 在不实际调用授权服务器的情况下模拟资源服务器中的安全上下文.
  2. 嵌入授权服务器作为测试的一部分并将身份验证重定向到它.

我想知道其他人是如何解决这个问题的.

I was wondering how others have approach this problem.

推荐答案

我使用 spring security 4.x @WithSecurityContext('user') 注解创建mock SecurityContext'user' 登录.然后在使用 MockMvc 调用我的 REST API 时,我检索 SecurityContext 并将其附加到调用中.

I use spring security 4.x @WithSecurityContext('user') annotation to create mock SecurityContext with 'user' logged in. Then when calling my REST API using MockMvc I retrieve SecurityContext and attach it to the call.

像这样:

@Test
@Transactional
@WithSecurityContext('user')
public void getAllParcels() throws Exception {
    // Initialize the database

    long size = parcelRepository.count();
    parcelRepository.saveAndFlush(parcel);

    // Get all the parcels
    restParcelMockMvc.perform(get("/api/parcels").with(security()))
        .andExpect(status().isOk())
        .andExpect(content().contentType(MediaType.APPLICATION_JSON))
        .andExpect(jsonPath("$.[" + size + "].id").value(parcel.getId()))
        .andExpect(jsonPath("$.[" + size + "].lot").value(DEFAULT_LOT))
        .andExpect(jsonPath("$.[" + size + "].localName").value(DEFAULT_LOCAL_NAME));
}

其中 security() 是静态方法:

public static RequestPostProcessor security() {
        return SecurityMockMvcRequestPostProcessors.securityContext(SecurityContextHolder.getContext());
}

因此,使用 @WithSecurityContext('user') 模拟 SecurityContext 和登录 'user' 的已验证用户是为我的测试方法创建的.然后在该方法中,我检索此模拟 SecurityContext 并将其附加到 REST API 调用,以使我的 oAuth 认为用户已通过身份验证.这基本上是您在问题中建议的第一种方法.

So using @WithSecurityContext('user') mock SecurityContext with authenticated user with login 'user' is created for my test method. Then in that method I retrieve this mock SecurityContext and attach it to the REST API call to make my oAuth think user is allready authenticated. It's basically the first approach you suggested in your question.

为此,您必须将 OAuth 切换为有状态的测试.否则它不会工作.

For this to work you must switch your OAuth to be statefull for the tests. Otherwise it won't work.

就是这样:

@Configuration
public class OAuth2ServerConfiguration {

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Autowired(required = false)
        @Qualifier("oauth2StatelessSecurityContext")
        private Boolean stateless = Boolean.TRUE; // STATEFUL switching for tests!

        @Inject
        private Http401UnauthorizedEntryPoint authenticationEntryPoint;

        @Inject
        private AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler;

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .logout()
                .logoutUrl("/api/logout")
                .logoutSuccessHandler(ajaxLogoutSuccessHandler)
                .and()
                .csrf()
                .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
                .disable()
                .headers()
                .frameOptions().disable().and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/api/authenticate").permitAll()
                .antMatchers("/api/register").permitAll()
                .antMatchers("/api/logs/**").hasAnyAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/api/**").authenticated()
                .antMatchers("/metrics/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/health/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/dump/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/shutdown/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/beans/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/configprops/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN)
                .antMatchers("/protected/**").authenticated();
        }

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.stateless(stateless);
            super.configure(resources);
        }

    }
...

你会看到我的 stateless 属性,它只在测试中被注入.在正常运行中,它使用它的默认值 true (所以它是无状态的).对于测试,我声明 oauth2StatelessSecurityContext Bean 的值为 false,因此它为测试变为有状态.

You see my stateless property which gets injected only in tests. In normal run it uses it's default value true (so it's stateless). For tests I declare oauth2StatelessSecurityContext Bean with value false so it turns statefull for tests.

我为测试定义了这个配置:

I define this configuration for tests:

@Configuration
public class OAuth2Statefull {

    @Bean
    @Primary       
    public Boolean oauth2StatelessSecurityContext() {
        return Boolean.FALSE;
    }

}

我就是这样做的.我希望我的解释是可以理解的.

That's how I did it. I hope my explanation is understandable.

这篇关于Spring OAuth 和引导集成测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆