HTTP Status 403. - Не удалось проверить предоставленный токен CSRF в тесте JUnit с помощью WireMock - PullRequest
0 голосов
/ 07 марта 2020

Я работаю в приложении, которое взаимодействует со сторонним API для создания пользователей и требует токен на предъявителя авторизации. Когда я запускаю службу и создаю запрос, используя Postman и токен-носитель теста, он работает нормально.

Проблема возникает, когда я пытаюсь запустить тест JUnit (плюс Wiremock), включающий эту функцию, я получаю сообщение: HTTP Status 403 - Could not verify the provided CSRF token because your session was not found.

Я спросил об этом Google и нашел несколько «исправлений» в некоторых сценариях ios (не для модульного тестирования, к сожалению), но они, похоже, не работают, поэтому я Хотелось бы знать, возможно, кто-то из SO-сообщества сталкивался с чем-то подобным.

Вот код моего модульного теста с использованием Wiremock:

@RunWith(SpringRunner.class)
@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.properties")
@ContextConfiguration(classes = { AppConfiguration.class, ThirdPartyServiceAutoConfiguration.class})
public class UserManagementServiceImplTest {

    @ClassRule
    public static WireMockRule wireMockRule = new WireMockRule(options().httpsPort(8443));

    @Autowired
    @Qualifier("thirdPartyRestTemplate")
    private RestTemplate restTemplate;

    @Autowired
    private ThirdPartyProperties authProperties;

    private UserManagementService service;

    @Before
    public void setUp() {
        service = new UserManagementServiceImpl(restTemplate, authProperties);
    }

    @Test
    public void testSuccessfulCreateUser() throws UserCreationFailedException {
        stubFor(post("/v1/orgId/user")
            .willReturn(aResponse()
                    .withStatus(200)
                    .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                    .withHeader(HttpHeaders.AUTHORIZATION, "Bearer MmgzMzJoMxifLs-wMmiaqGcuVSNmIH8pWgp6CgVacSBDA1lZWyECSDJoMmtmDm0MClFWOGMpRyV5XVcpXDhYJUQhfCZ2KQclZipYMV891c4YiTkHlj_yfvuSdGUcCA")
                    .withBody(
                            "{\"code\":\"RESPONSE_SUCCESS\",\"data\": {\"binder_id\":\"BouGfLpXeoTIgdugaYsgioE\","
                                    + "\"id\":\"UGD8pJCrY0bJFmbLnWoZ0i1\",\"relation_id\": 4}}"))
            .withRequestBody(equalToJson("{\"unique_id\": \"client_01\",\"first_name\": \"Unique ID Client 1\","
                    + "\"last_name\": \"Generic Last Name\",\"admin\": false,\"user_type\":\"Client\","
                    + "\"user_email\": \"internal-user-01@domain.com\",\"phone_number\": \"408-555-1234\"}", 
                    true, true)));

            CreateUserResponse userCreationResponse = service.createUser(orgId(), createClientUserRequest());

            assertNotNull("response shouldn't be null", userCreationResponse);
            assertThatResponseIsEqual(userCreationResponse);
    }

    private CreateClientUserRequest createClientUserRequest() {
        return new CreateClientUserRequest("client_01", "Unique ID Client 1", "Generic Last Name", 
                "internal-user-01@domain.com", "408-555-1234", false, CommonApplicationConstants.USER_TYPE_CLIENT,
                "MmgzMzJoMxifLs-wMmiaqGcuVSNmIH8pWgp6CgVacSBDA1lZWyECSDJoMmtmDm0MClFWOGMpRyV5XVcpXDhYJUQhfCZ2KQclZipYMV891c4YiTkHlj_yfvuSdGUcCA");
    }

    private String orgId() {
        return "orgId";
    }
}

Эта часть, которая вызывает сервис с использованием Spring RestTemplate:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add(HttpHeaders.AUTHORIZATION, String.format("%s %s", "Bearer", createClientUserRequest.getAuthToken()));

HttpEntity<CreateClientUserRequest> request = new HttpEntity<ClientUserRequest>(createClientUserRequest, headers);

response = restTemplate.postForEntity(authProperties.getV6AuthUrl() + CREATE_USER_SERVER_PATH.replace("{ORG_ID}", orgId), 
                request, CreateUserResponse.class);
createClientUserResponse = response.getBody();

У меня есть конфигурация для шаблона отдыха:

@Bean("thirdPartyRestTemplate")
    public RestTemplate restTemplate() throws Exception {
        HttpClientBuilder httpClientBuilder = RestTemplateUtil.createHttpClientBuilder(authProperties)
                .disableRedirectHandling();

        if (authProperties.isVerificationForSSLdisabled()) {
            httpClientBuilder = httpClientBuilder.setSSLContext(createSSLContext((certificate, authType) -> true))
                    .setSSLHostnameVerifier(new NoopHostnameVerifier());
        } else {
            httpClientBuilder = httpClientBuilder.setSSLContext(createSSLContext(null));
        }

        final HttpComponentsClientHttpRequestFactory requestFactory = RestTemplateUtil
                .createClientHttpRequestFactory(authProperties, httpClientBuilder.build());

        return new RestTemplate(requestFactory);
    }

Я попытался исправить проблему, добавив следующую конфигурацию:

@Configuration
    @EnableWebSecurity
    @EnableConfigurationProperties({ AppProperties.class, OtherProperties.class })
    public class AppConfiguration extends WebSecurityConfigurerAdapter {

        @Value("${security.enable-csrf}")
        private boolean csrfEnabled;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            super.configure(http);
            if (!csrfEnabled) {
                http.csrf().disable();
            }
        }

    }

Использование свойства CSRF (для файла свойств теста значение равно false): security .enable-csrf

Но я всегда получаю

DEBUG org.apache.http.wire - http-outgoing-0 << "<html><head><title>Error report</title></head><body><h1>HTTP Status 403 - Could not verify the provided CSRF token because your session was not found.</h1></body></html>"

Если у кого-то есть какие-либо подсказки или предложения, я буду очень ценю вашу помощь. Заранее спасибо.

...