域中的端口拒绝 cookie

Port in Domain rejects cookie

我正在连接到一个 RESTful API,它有一个登录资源:/login。使用他们给我的凭据,结果很好 200。 但是之后尝试访问受保护的资源给了我一个 401(它 确实 与 Firefox 插件 RESTClient 一起工作,尽管如此)。调试后,我发现有些 cookie 被拒绝了,我认为这是不让我进入的原因。

他们身上的警告信息是:

Cookie rejected [somename="somevalue", version:0, domain:xyz.org:443, path:/, expiry:null] Illegal 'domain' attribute "xyz:443". Domain of origin: "xyz"

我正在使用 Apache HTTP 客户端 httpcomponents-client-4.5.6 连接到站点。有什么我可以做的吗?据我所知,唯一困扰它的是:443。 API 只能通过 https 访问。我没有发现我是否可以使用 httpclient 更改我对该站点的访问权限,因此它不再看到域名的差异。

我进行了大量搜索,找到了许多关于 CookieSpecProviders 并将 CookieSpecs 设置为 "easy" 的过时解决方案 - 但所有这些似乎完全消除了所有 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("whosebug.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 请求,这导致了正确的行为。 'prov' cookie(应该是某种会话 cookie)保持不变。对上述 API 做同样的事情会给出错误。

我不知道是否有必要这样做,但为了解决这个问题,我根据不同来源的建议创建了一个新的 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,现在它可以工作了。