очистить куки с RestTemplate перед выполнением HTTP-вызова - PullRequest
0 голосов
/ 04 июня 2018

Я использую Spring-Boot 2.0.2 RestTemplate для создания следующего сценария:

Я - Потребитель отдыха (клиент), которому:

  1. сначала нужновойдите в систему Spring-Security-Check
  2. , затем сделайте второй вызов для получения данных.

Сначала я подумал сделать вызов авторизации и вручную прочитать файл cookie JSESSIONID.из SET-COOKIE и установите его на второй вызов в заголовке.Вот моя первая попытка:

RestClient:

@Service
public class RestClient {
    private static final String ENDPOINT_DATA = "/data";
    private static final String ENDPOINT_SECURITY_CHECK = "/j_spring_security_check";

    private static final String HTTP_HEADER_KEY_SET_COOKIE = "Set-Cookie";
    private static final String HTTP_HEADER_KEY_COOKIE = "Cookie";

    private static final String PROPERTY_SPRING_SECURITY_USER = "j_username";
    private static final String PROPERTY_SPRING_SECURITY_PASS = "j_password";

    private final RestTemplate restTemplate;
    private final RestConfig restConfig;

    @Autowired
    public RestClient(RestTemplateBuilder restTemplateBuilder, final RestConfig restConfig) {

        notNull(restTemplateBuilder, "restTemplateBuilder must not be null!");
        this.restTemplate = restTemplateBuilder
                .additionalCustomizers(new NoRedirectionHandlingRestTemplateCostumizer())
                .build();

        notNull(restConfig, "openIdConfig must not be null!");
        this.restConfig = restConfig;
    }

    public String getData() {
        final String jSessionCockie = jSpringSecurityLogin();
        return getAuthorizeCode(jSessionCockie);
    }

    private String jSpringSecurityLogin() {
        // read config
        final String fullLoginUri = restConfig.getUrl() + ENDPOINT_SECURITY_CHECK;
        final String user = restConfig.getUser();
        final String password = restConfig.getPassword();

        // Build entity that is send
        final HttpHeaders headers = new HttpHeaders();
        final String body = PROPERTY_SPRING_SECURITY_USER + "=" + user + "&" + PROPERTY_SPRING_SECURITY_PASS + "=" + password;
        final HttpEntity<String> toSend = new HttpEntity<>(body, headers);

        final String jSessionIdCockie;

        final ResponseEntity<String> response = restTemplate.postForEntity(fullLoginUri, toSend, String.class);

        // Get String "JSESSIONID=XXXX". If there are other Cookies, propably will fail.
        if (HttpStatus.FOUND.equals(response.getStatusCode()) && response.getHeaders().containsKey(HTTP_HEADER_KEY_SET_COOKIE)) {
            jSessionIdCockie = response.getHeaders().get(HTTP_HEADER_KEY_SET_COOKIE).get(0);
        } else {
            throw new Error();
        }

        return jSessionIdCockie;
    }

    private String getAuthorizeCode(final String jSessionCockie) {
        // read config
        final String fullDataUri = restConfig.getUrl() + ENDPOINT_DATA;

        // Build entity that is send
        final HttpHeaders headers = new HttpHeaders();
        headers.add(HTTP_HEADER_KEY_COOKIE, jSessionCockie);
        final HttpEntity<Void> toSend = new HttpEntity<>(headers);

        final ResponseEntity<String> response = restTemplate.exchange(fullDataUri, HttpMethod.GET, toSend, String.class);

        if (HttpStatus.OK.equals(response.getStatusCode()) && response.hasBody()) {
            return response.getBody();
        } else {
            return "";
        }
    }
}

Чтобы завершить, здесь используется Costumizer в конструкторе:

class NoRedirectionHandlingRestTemplateCostumizer implements RestTemplateCustomizer {
    @Override
    public void customize(RestTemplate restTemplate) {
        final HttpClient httpClient = HttpClientBuilder.create()
                .disableRedirectHandling()
                .build();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }
}

Теперь, когда я сделаю несколькоФункциональные тесты с помощью Wiremock Я вижу следующие данные в истории запроса на получение Wiremock для вызова данных:

{
  ...
  "headers":
  {
    "Cookie": [
      "JSESSIONID=axcvueiornxniuwherwuieoiun,asdpfoiu",
      "JSESSIONID=axcvueiornxniuwherwuieoiun,asdpfoiu"
    ],
    ...
  },
  "cookies":
  {
    "JSESSIONID": [
      "axcvueiornxniuwherwuieoiun,asdpfoiu",
      "axcvueiornxniuwherwuieoiun,asdpfoiu"
    ]
  }
  ...
}

Ожидание - JSESSIONID устанавливается 2 раза.Крутой REST обрабатывает это для меня!

Вторая попытка: я могу удалить передачу Cookie.И это работает.

Но при первой и второй попытках возникают проблемы: после первого вызова RestClient.getData() все последующие вызовы конечной точки входа в систему также имеют установленный JSESSIONID.Я не знаю, как Рест-продюсер может справиться с этим (время ожидания сеанса и т. Д.).

Теперь моя проблема / вопрос:

Я хотел бы заставить RestTemplate забыть / стереть все куки-файлы перед тем, как выполнить вход в систему (описание причины ранее).Есть ли возможность?Я не нашел ничего работающего.


Мой обходной путь сейчас состоит в том, чтобы отключить управление Cookie RestTemplate и делать все вручную, как при первой попытке.Отключение CookieManagment может быть выполнено через RestTemplateCustomizer:

class NoRedirectionHandlingRestTemplateCostumizer implements RestTemplateCustomizer {
    @Override
    public void customize(RestTemplate restTemplate) {
        final HttpClient httpClient = HttpClientBuilder.create()
                .disableRedirectHandling()
                .disableCookieManagement()
                .build();
        restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient));
    }
}
...