【问题标题】:Disable or mocking OAuth2 for integration test in Spring Boot在 Spring Boot 中禁用或模拟 OAuth2 以进行集成测试
【发布时间】:2017-06-27 15:51:15
【问题描述】:

我正在尝试在运行集成测试时禁用/模拟本地 OAuth2 服务器,但到目前为止,这样做的大多数方法都涉及我没有使用的 Spring MVC。这是最常见的解决方案:

 this.mockMvc = MockMvcBuilders
            .webAppContextSetup(webApplicationContext)
            .apply(springSecurity())
            .build();

在 Spring Boot 上,我有一个 TestRestTemplate 用于端点上的请求。我在测试中有这个:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    properties = {"eureka.client.enabled:false"})
public class ApiControllerTest {



 @Test
    @WithOauth2TestAuthentication
public void employeesPost() throws Exception {
    HttpHeaders headers = new HttpHeaders();
    headers.add(HttpHeaders.AUTHORIZATION, "Bearer FOO");
    headers.add(HttpHeaders.CONTENT_TYPE, "application/json");

    ResponseEntity<OperationResultDTO> responseEntity =
            this.restTemplate.postForEntity("/employees", new HttpEntity<>(loggedEmployee, headers), OperationResultDTO.class);
    assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, responseEntity.getStatusCode());
}
}

注释:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
@WithSecurityContext(factory = WithOAuth2AuthenticationSecurityContextFactory.class)
public @interface WithOauth2TestAuthentication {
    String clientId() default "temporal";

    String username() default "username";

    String[] scopes() default { "read", "write", "trust" };
}

SecurityContextFactory:

public class WithOAuth2AuthenticationSecurityContextFactory
    implements WithSecurityContextFactory<WithOauth2TestAuthentication> {
@Override
public SecurityContext createSecurityContext(WithOauth2TestAuthentication annotation) {
    Set<String> scopes = new HashSet<>();
    Collections.addAll(scopes, annotation.scopes());

    OAuth2Request oAuth2Request = new OAuth2Request(null, annotation.clientId(),
            null, true, scopes, null, null,
            null, null);
    Authentication auth2Authentication = new OAuth2Authentication(oAuth2Request,
            new TestingAuthenticationToken(annotation.username(), null, "read"));

    SecurityContext context = SecurityContextHolder.createEmptyContext();
    context.setAuthentication(auth2Authentication);
    return context;
}
}

到目前为止,每次测试运行都会给我一个断言错误,这意味着请求返回 401 而不是我想要的 422。我尝试使用以下说明伪造 OAuth 服务器:http://engineering.pivotal.io/post/faking_oauth_sso/ 无济于事(我也试图避免它,但我的拍摄没有成功)。我也可以模拟授权令牌,但我不确定如何在此处执行此操作。

【问题讨论】:

  • 您找到解决方案了吗?

标签: spring integration-testing spring-security-oauth2


【解决方案1】:

我最终做的是将 OAuth2 配置文件放在不同的 @Profile 上,并为每个控制器测试创建一个抽象类,使用带有 @AutoConfigureMockMvc 的 MockMvc:

@AutoConfigureMockMvc
@SpringBootTest
@ActiveProfiles({ "default", "local", "test" })
abstract class BaseControllerTest {
}

@RunWith(SpringRunner.class)
public class SampleControllerTest extends BaseControllerTest {
    @Autowired
    private MockMvc mockMvc;
// ...

    @Test
    @WithMockUser
    public void aTest() throws Exception {
        MvcResult result =
            mockMvc.perform(get(URL_TEMPLATE).with(csrf()))
                    .andExpect(status().isOk())
                    .andReturn();
    }
}

通过该设置,SecurityContext 确实返回了一个模拟用户,这最终导致我的请求因 401 HTTP 代码而失败。如果我需要针对 Unprocessable Entity 响应,只需将 status().isOk() 切换为 status().isUnprocessableEntity()

【讨论】:

    猜你喜欢
    • 2018-05-04
    • 2017-10-27
    • 2018-07-16
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 2020-07-24
    • 2021-04-09
    相关资源
    最近更新 更多