Есть следующий код:
private static readonly HttpClientHandler handler = new HttpClientHandler
{
CookieContainer = new CookieContainer(),
UseCookies = true
};
private static readonly HttpClient httpClient = new HttpClient(handler);
public Class1()
{
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.0.1308.1016 Safari/537.36");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip, deflate");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Language", "ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4");
}
Сохранение кук в виде json:
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filename = Path.Combine(path, "test/cookies.bin");
if (File.Exists(filename)) File.Delete(filename);
var cookies = handler.CookieContainer.GetCookies(new Uri("https://site.ru/"));
using var fs = new FileStream(filename, FileMode.OpenOrCreate);
await JsonSerializer.SerializeAsync(fs, cookies);
Загрузка кук:
string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string filename = Path.Combine(path, "test/cookies.bin");
using var fs = new FileStream(filename, FileMode.Open);
var cookies = await JsonSerializer.DeserializeAsync<List<Cookie>>(fs);
foreach (var cookie in cookies)
{
handler.CookieContainer.Add(cookie);
}
Куки в файле:
[{"Comment":"","CommentUri":null,"HttpOnly":true,"Discard":false,"Domain":"site.ru","Expired":false,"Expires":"0001-01-01T00:00:00","Name":"__RequestVerificationToken","Path":"/","Port":"","Secure":true,"TimeStamp":"2020-10-09T13:33:07.1633063+03:00","Value":"D4cK7wXeq6KThXJG0uZJ8gxUZQ_jGr1pNUwrCuJEhlKVeQHiLQzbvdkZXxmcWT8oYRt4ipPUes4D0dMTxbgY_2yZnJUZxM03F7n0AVtFShU1","Version":0},{"Comment":"","CommentUri":null,"HttpOnly":true,"Discard":false,"Domain":"site.ru","Expired":false,"Expires":"2020-10-11T13:33:08+03:00","Name":".ASPXAUTH","Path":"/","Port":"","Secure":false,"TimeStamp":"2020-10-09T13:33:07.6753356+03:00","Value":"824040565E5BCCD7A57ECDFC3BF4A3D5BEFF477161636356924B0340E53F1527470E6513BE272EDB9392A05C652542ED27F5A001D92DFDE5F395BD1D75708F60CCF2DE2D40ACDF1B8D82743D8CED67713FE85653BB04716B534FA3CEAD261FC9BED4BA50A21C9D2C989FDB2EF1D9ADE4","Version":0}]
GET запрос через браузер:
GET запрос через программу:
Дело в том, что после загрузки кук я не получаю ту страницу, которую должен, а получаю страницу авторизации. Судя по всему, проблема в том, что у меня как бы "не загружается" кука .ASPXAUTH.. и на изображение из браузера видно другие куки (_ym_uid и другие..), я не могу понять, они обязательны или нет?
Ранее с куками дел не имел, подскажите, пожалуйста, в чем дело?
UPD:
private static readonly HttpClientHandler handler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
AllowAutoRedirect = true
};
private static readonly HttpClient httpClient = new HttpClient(handler);
public HttpManager()
{
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 UBrowser/6.0.1308.1016 Safari/537.36");
httpClient.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip, deflate, br");
}
Получаю куки теперь так:
var cookies = handler.CookieContainer.GetAllCookies();
Загружаю так:
List<Cookie> cookies = await JsonSerializer.DeserializeAsync<List<Cookie>>(fs);
foreach (var cookie in cookies)
{
// не загружать, если кука заэкспайрилась
if (!cookie.Expired && (cookie.Expires == DateTime.MinValue || cookie.Expires > DateTime.Now))
handler.CookieContainer.Add(cookie);
}
Этот класс позаимствовал по ссылке которую написали в комментариях:
public static class CookieContainerExtensions
{
// Забирает все куки из контейнера
public static CookieCollection GetAllCookies(this CookieContainer container)
{
CookieCollection allCookies = new CookieCollection();
IDictionary domains = (IDictionary)container.GetType()
.GetRuntimeFields()
.FirstOrDefault(x => x.Name == "m_domainTable")
.GetValue(container);
foreach (object field in domains.Values)
{
IDictionary values = (IDictionary)field.GetType()
.GetRuntimeFields()
.FirstOrDefault(x => x.Name == "m_list")
.GetValue(field);
foreach (CookieCollection cookies in values.Values)
{
allCookies.Add(cookies);
}
}
return allCookies;
}
}
К сожалению, на деле получаю то, что получал ранее. Видать, я что-то упускаю из виду..


_ym- это яндекс.метрика._ga- гуглоаналитика. – aepot Oct 09 '20 at 10:5913:33:07. 2. Не совпадают ключи - иногда делают так, что сайт требует 2+ ключа доступа и они связаны, и вот если один из них битый, то сайт не считает это успешной авторизацией. 3. - Неверно указанURI- Cookie очень сильно завязаны на адресе, особенно в C# и, если печенька для.site.ru(точка в начале), то это не равно простоsite.ru(без точки), проверьте, правильный-ли вы адрес получаете и задаете при сохранении/восстановлении. По поводу "лишнее" - скорей всего да, как и все, что у вас вClass1. – EvgeniyZ Oct 09 '20 at 11:04e.site.ru(правильно), в коде именно так везде и указано. Единственное, что я заметил сейчас, это то, что когда в браузере перед авторизацией ставлю чекбоксЗапомнить, то вPOSTзапрос отправляется так:Remember=true, Remember=false, т.е, для первого ключа указаноtrue, для второго -false. Но у меня два раза добавить ключ в коллекциюDictionary, естественно, не получается (ошибка). – Максим Oct 09 '20 at 12:49"Domain":"site.ru", а вы пишете сейчасe.site.ru, уж определитесь. Далее, вам достаточно всего 1-2-х Cookie для авторизации, зачем десериализировать весь словарь? Найдите нужную, зайдите на сайт через Postman и уже затем пишите код. – EvgeniyZ Oct 09 '20 at 12:52e.site.ru, это я когда сюда выкладывал намудрил, извиняюсь. На счет остального - сейчас буду пробовать, спасибо. – Максим Oct 09 '20 at 12:54UserAgent,AcceptEncoding,AutomaticDecompression,AllowAutoRedirect). – EvgeniyZ Oct 09 '20 at 12:59getзапрос на страницу авторизации; 2) Беру в исходнике этой страницы токен; 3) Отправляю все данные (токен, логин, пароль)postзапросом, приходит правильный ответ с куками (вижу свои данные); 4) Отправляюgetзапрос на главную страницу с одной кукой (токен) - авторизация НЕ УДАЛАСЬ, добавляю к этой куке вторую куку.ASPXAUTH- авторизация УДАЛАСЬ. Позже выяснил, что можно только одну куку.ASPXAUTHдобавлять и она будет "подтягивать" за собой вторую. – Максим Oct 09 '20 at 14:53.ASPXAUTH– Максим Oct 09 '20 at 14:53ничего не изменилось- а должно было? Она вам помогла выяснить именно то, что необходимо отправить этому сайту для успешной авторизации, все лишнее теперь можете убрать, включая сериализацию/десериализацию всей коллекции печенек, достаточно лишь значение этого.ASPXAUTHв виде простой строки). Также мне не нравиться эта строка -handler.CookieContainer.Add(cookie);(вангую, что там теряется адрес), а также мне не нравиться то, что вы не устанавливаетеBaseAdress(с которым связываются Cookie). Попробуйте нечто такое. – EvgeniyZ Oct 09 '20 at 15:13