Сохраните / Загрузите "Browser" -сессию HttpClient в c # - PullRequest
0 голосов
/ 29 августа 2018

У меня есть приложение Webcrawler, которое использует HttpClient для выполнения некоторых запросов.

Когда я запускаю приложение, инициализируется новый HttpClient, подобный следующему:

public static void ResetHttpClient()
{
    Client = new HttpClient();
}

После перезапуска приложения приложение должно войти в систему заново, что вызывает проблемы из-за ограничений на n входов в час.

Из-за этого я скопировал функцию из другой части моего Apllication, которая сериализует список> и сохраняет этот список в файл.

Я адаптировал функцию, чтобы протестировать ее с помощью HttpClient. Мое намерение состояло в том, чтобы сохранить HttpClient, а затем, когда программа запустится / перезапустится, загрузить HttpClient и продолжить «Сеанс». Код для функции сохранения (я знаю, это очень некрасиво со списком только для одной записи):

// SAVE
(HttpClient client, DateTime clientCreationDate) httpClientSaveData = 
    new ValueTuple<HttpClient, DateTime>(Client, ClientCreatedDate);
FileStream stream = new FileStream(@"HttpClient.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, httpClientSaveData);
stream.Close();

С этим кодом выше я получаю следующее сообщение об ошибке:

System.Runtime.Serialization.SerializationException: 'Тип' System.Net.Http.HttpClient 'в сборке' System.Net.Http, версия = 4.0.0.0, культура = нейтральная, PublicKeyToken = b03f5f7f11d50a3a 'не помечена как сериализуемая .

Теперь мой вопрос: возможно ли даже сохранить / загрузить «Сессию», например, путем сохранения файлов cookie? Что может быть жизнеспособным подходом к этому?

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Решение, которое работало для меня, состояло в том, чтобы сохранить CookieContainer в файл и загрузить его. Для этого я создал две следующие функции:

/// <summary>
/// this function loads the CookieContainer that contains the Session Cookies
/// </summary>
public static void LoadHTTPClient()
{
    CookieJar = new CookieContainer();
    if (File.Exists(@"ClientSessionCookies.dat"))
    {
        // LOAD
        FileStream inStr = new FileStream(@"ClientSessionCookies.dat", FileMode.Open);
        BinaryFormatter bf = new BinaryFormatter();
        CookieJar = bf.Deserialize(inStr) as CookieContainer;
        inStr.Close();
    }
    var handler = new HttpClientHandler
    {
        CookieContainer = CookieJar,
        UseCookies = true,
    };
    Client = new HttpClient(handler);
}

/// <summary>
/// this function saves the sessioncookies to file
/// </summary>
/// <param name="CookieJar"></param>
public static void SaveHTTPClient(CookieContainer CookieJar)
{
    // SAVE client Cookies
    FileStream stream = new FileStream(@"ClientSessionCookies.dat", FileMode.Create);
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, CookieJar);
    stream.Close();
}

спасибо @AlexK и @ADyson за подсказку

Я бы предположил, что процесс входа в систему, вероятно, выдает cookie в ожидании, что браузер сохранит его для использования в будущих запросах. Так работает большинство систем входа в систему на основе браузера. Возможно, вы сможете получить это, а затем использовать его до истечения срока его действия. Боюсь, что я не знаю, как это сделать, но, возможно, если вы будете искать использование куки с C # HttpClient, вы можете начать свой путь в правильном направлении. - ADyson

-

Cookies (через заголовок HTTP) - это механизм, с помощью которого HTTP-запрос согласовывается с сеансом сервером, они доступны для чтения / записи с помощью HttpClient, например. stackoverflow.com/questions/13318102/… - Алекс К.

0 голосов
/ 29 августа 2018

Ошибка возникает из-за того, что вы пытаетесь сериализовать объект, который не имеет атрибута [Serializable]. Поскольку это базовый класс, вы также не можете добавить его.

Объект HttpClient предназначен для повторного использования, это просто вопрос того, как в вашем приложении. Как правило, вы оборачиваете фреймворк HttpClient в класс, который выполняет определенное действие, которое вам требуется, и используете его как Singleton.

Похоже, что это более или менее то, что вы делаете, поэтому проблема в том, что ваше приложение часто запускается и останавливается, что приводит к воссозданию объекта.

Если вы хотите что-то запускать периодически, сохраняя состояние, тогда лучшим инструментом для работы будет Служба Windows

Если вы выполняете свой запрос на основании получения другого запроса в своем веб-приложении, вам следует использовать Dependency Injection с областью действия Singleton. Это сохранит объект живым, пока включен пул приложений. При необходимости вы можете увеличить время простоя в IIS. Я думаю, что по умолчанию это 15 минут, что гарантирует не более 4 входов в час.

EDIT:

Поскольку основная проблема заключается в разработке и тестировании, вам следует немного обмануть. Используя прокси, такой как Fiddler, вы можете записать шаги, предпринятые для входа в систему вручную. На что нужно обратить внимание - это заголовки Http. Большинство данных типа аутентификации / сеанса будут либо в заголовке Cookie, либо в заголовке Authorization. Также могут быть заголовки типа X-Session-ID или аналогичные. Вы должны иметь возможность вручную скопировать заголовки после успешного входа в систему, а затем вставить их в свой код. Такой клиент, как Postman, может быть очень полезен для точного определения, какие именно заголовки требуются.

Ваш код может выглядеть следующим образом:

public static void ResetHttpClient()
{
    Client = new HttpClient();

    if (isDevelopment) // however you determine it
    {
         Client.DefaultRequestHeaders
               .TryAddWithoutValidation("Authorization", "Bearer hhxcshRT43bhJHjh53hkjhbhvghf54g5hbhkghfdUGUKGYFDJihu5");
         Client.DefaultRequestHeaders
               .TryAddWithoutValidation("Cookie", "SessionID=36dab-3545-adef");
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...