PHP + Curl: закрытие соединения во время согласования аутентификации (HTTP 1.0?) - PullRequest
5 голосов
/ 08 октября 2019

У меня проблема между CURL и PHP. Я пытался подключиться к серверу Exchange 2010 через EWS. Подключение к серверу работает нормально в командной строке, используя CURL, но не с расширением PHP Curl.

Я приложил изображение с отладочной информацией. Слева вы видите вывод командной строки, справа - подробный вывод PHP. Когда расширение PHP Curl выдает ошибку «Закрытие соединения при согласовании авторизации (HTTP 1.0?)», Командная строка продолжается с третьим HTTP-запросом с результатами в HTTP / 1.1 302 Найдено:

log information

Некоторая дополнительная информация:

  • Я использую эту библиотеку для CURL-запросов: https://github.com/jamesiarmes/php-ntlm/blob/master/src/SoapClient.php
  • у нас около 80 серверов обмена, где естьбез проблем. Только с этим сервером есть проблемы. Наш клиент рассказал о программном обеспечении «Sophos», используемом в качестве прокси-сервера для веб-сервераИнформация 7.63.0 / 7.52.1 также протестирована

Кто-нибудь знает, почему PHP Curl Extension закрывает соединение перед третьим запросом? Это ошибка расширения, могу ли я использовать константу PHP Curl, чтобы избежать этого, или есть другое решение?

Ответы [ 2 ]

3 голосов
/ 10 октября 2019

Соединение закрыто, потому что сервер так говорит. Смотрите на скриншот, на одну строку выше, где "В чем проблема здесь?"Очки.

HTTP/1.1 401 Unauthorized
[...]
Connection: close
Content-Type: application/x-asmx

И, вероятно, сервер впоследствии закрывает соединение.

Так что это не действие, а результат. Сообщение отправляется в Curl_http_readwrite_headers:

#if defined(USE_NTLM)
      if(conn->bits.close &&
         (((data->req.httpcode == 401) &&
           (conn->http_ntlm_state == NTLMSTATE_TYPE2)) ||
          ((data->req.httpcode == 407) &&
           (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) {
        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
        data->state.authproblem = TRUE;
      }
#endif
#if defined(USE_SPNEGO)
      if(conn->bits.close &&
        (((data->req.httpcode == 401) &&
          (conn->http_negotiate_state == GSS_AUTHRECV)) ||
         ((data->req.httpcode == 407) &&
          (conn->proxy_negotiate_state == GSS_AUTHRECV)))) {
        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
        data->state.authproblem = TRUE;
      }

Предположительно из первого блока (NTLM), но это два вхождения, и они все равно находятся рядом друг с другом.

Интересный факт: та же самая функция только много позже проверяет наличие заголовка Connection: close, поэтому установка мистического флага conn->bits.close, вероятно, означает, что сервер уже разорвал соединениеи это было обнаружено на уровне сокетов.

Примечание: две стороны сравнения показывают очень разнородные взаимодействия. Слева находится практически пустой запрос GET (предоставляются заголовки Host, Authorization, User-Agent и Accept), а справа - более сложный запрос POST (такой жезаголовки плюс Method, SOAPAction, пустой контент с Expect для продолжения).

1 голос
/ 11 октября 2019

Я сталкивался с подобной проблемой, используя SoapClient и Microsoft Exchange 2010 Server, и хитрость заключалась в изменении параметра массива заголовков 'Expect: 100-continue' на 'Expect: 200-ok '

protected function buildHeaders($action)
{
    return array(
        'Method: POST',
        'Connection: Keep-Alive',
        'User-Agent: PHP-SOAP-CURL',
        'Content-Type: text/xml; charset=utf-8',
        "SOAPAction: \"$action\"",
        'Expect: 200-ok',
    );
}

Код состояния 100 (Продолжить) указывает, что начальная часть запроса была получена и еще не была отклонена сервером.

Код состояния 200 (ОК) указывает на успешное выполнение запроса. Значение успеха зависит от метода HTTP.

Вы также можете проверить это Коды состояния HTTP

Хотелось бы, чтобы это помогло

...