Порт в домене отклоняет куки

Я подключаюсь к RESTful API, у которого есть ресурс для входа: /login. Используя учетные данные, которые они мне дали, это приводит к хорошему 200. Но попытка получить доступ к защищенным ресурсам после этого дает мне 401 (однако он действительно работает с надстройкой RESTClient для Firefox). После отладки я обнаружил, что некоторые файлы cookie отклоняются, и я полагаю, что они не пускают меня.

Предупреждающее сообщение на них:

Файл cookie отклонен [somename="somevalue", версия:0, домен:xyz.org:443, путь:/, срок действия:null] Недопустимый атрибут "домен" "xyz:443". Домен происхождения: "xyz"

Я использую HTTP-клиент Apache httpcomponents-client-4.5.6 для подключения к сайту. Могу ли я что-нибудь сделать? Насколько я вижу, единственное, что его беспокоит, это: 443. API доступен только через https. Я не выяснил, могу ли я изменить свой доступ к сайту с помощью httpclient, поэтому он больше не видит разницы в доменных именах.

Я много искал и пришел ко многим устаревшим решениям, касающимся CookieSpecProviders и настройке CookieSpecs на «легкий», но все это, казалось, полностью устранило все файлы cookie. Мой отладочный вывод хранилища файлов cookie всегда был пустым после использования этих решений (но предупреждающие сообщения исчезли).

Я создал быстрый и грязный, изолированный пример:

package apitest;

import java.io.IOException;

import org.apache.http.HttpHost;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;

public class ApiTest {
    public static void main(String[] args) {
        HttpHost target = new HttpHost("stackoverflow.com", 443, "https");
        HttpClientContext context = HttpClientContext.create();
        CookieStore cookieStore = new BasicCookieStore();

        HttpClientBuilder clientBuilder = HttpClientBuilder.create().setDefaultCookieStore(cookieStore);
        CloseableHttpClient httpClient = clientBuilder.build();

        HttpGet stackGet = new HttpGet("");
        CloseableHttpResponse response;

        try {
            response = httpClient.execute(target, stackGet, context);

            printCookies(cookieStore);
        } catch (IOException e) {
            e.printStackTrace();
        }

        stackGet = new HttpGet("/tags");
        try {
            response = httpClient.execute(target, stackGet, context);

            printCookies(cookieStore);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void printCookies(CookieStore cookieStore) {
        for (Cookie c : cookieStore.getCookies()) {
            System.out.println(c.getName() + " : " + c.getValue());
        }
    }
}

Выполняется два последовательных запроса GET, что приводит к правильному поведению. Файл cookie «prov», который должен быть своего рода файлом cookie сеанса, остается прежним. То же самое, проделанное с вышеупомянутым API, дает ошибку.


person Krann Sock    schedule 03.12.2018    source источник
comment
Добро пожаловать! Чтобы улучшить работу со Stack Overflow, прочитайте как спросить и вопрос по теме и вопрос Контрольный список и идеальный вопрос и как создать минимальный, полный и проверяемый пример и, если это еще не сделано, пройти экскурсию.   -  person Bsquare ℬℬ    schedule 03.12.2018
comment
Я не могу включить пример с использованием этого API, но я добавлю соответствующий код.   -  person Krann Sock    schedule 03.12.2018


Ответы (1)


Я не знаю, нужно ли было это делать, но чтобы решить эту проблему, я создал новый CookieSpec, как рекомендуется в разных источниках:

EasySpecProvider.class

import org.apache.http.cookie.CookieSpec;
import org.apache.http.cookie.CookieSpecProvider;
import org.apache.http.protocol.HttpContext;

class EasySpecProvider implements CookieSpecProvider {
    @Override
    public CookieSpec create(HttpContext context) {
        return new EasyCookieSpec();
    }
}

EasyCookieSpec.class

import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.MalformedCookieException;
import org.apache.http.impl.cookie.DefaultCookieSpec;

class EasyCookieSpec extends DefaultCookieSpec {
    @Override
    public void validate(Cookie arg0, CookieOrigin arg1) throws MalformedCookieException {
    }
}

Я зарегистрировал его через

Registry<CookieSpecProvider> r = RegistryBuilder.<CookieSpecProvider>create()
        .register("easy", new EasySpecProvider()).build();

а также

clientBuilder.setDefaultCookieSpecRegistry(r)
.setDefaultRequestConfig(RequestConfig.custom().setCookieSpec("easy").build())

в конструкторе клиентов. После этого все некорректные файлы cookie были приняты, но файл cookie сеанса менялся при каждом запросе. Я предполагаю, что то же самое затем произошло на сервере API (несоответствие доменной части файла cookie). Теперь я очищаю хранилище файлов cookie при каждом запросе и вручную воссоздаю файл cookie сеанса с правильным атрибутом домена, и теперь он работает.

person Krann Sock    schedule 04.12.2018