Sim*_*ars 9 java cookies httpclient java-11
我正在尝试使用 Java 11 HttpClient 获取页面的内容。由于该页面使用 OAuth,我想使用我的会话 cookie 进行身份验证。受这个问题的启发,我目前使用以下代码:
public static void main(String[] args) throws IOException, InterruptedException {
String year = args[0];
String day = args[1];
String session = System.getenv("AOCSESSION");
System.out.println(session);
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://adventofcode.com/"+year+"/day/"+day+"/input")).GET().build();
CookieManager cookieManager = new CookieManager();
HttpCookie cookie = new HttpCookie("session", session);
cookieManager.getCookieStore().add(URI.create("https://adventofcode.com"), cookie);
HttpClient client = HttpClient.newBuilder().cookieHandler(cookieManager).build();
String body = client.send(req, BodyHandlers.ofString()).body();
System.out.println(body);
}
Run Code Online (Sandbox Code Playgroud)
然而,请求结果未经身份验证(响应:)Puzzle inputs differ by user. Please log in to get your puzzle input.。我已经尝试向 cookie 添加其他字段:
cookie.setDomain(".adventofcode.com");
cookie.setMaxAge(Instant.parse("2031-11-01T18:26:23.293Z").getEpochSecond());
cookie.setPath("/");
cookie.setHttpOnly(true);
cookie.setSecure(true);
Run Code Online (Sandbox Code Playgroud)
但这并不能解决问题。
如何向请求添加会话 cookie?
Sus*_*afa 10
解决方案如下,使用适当的 CookieManager 而不是硬编码标头:
\npublic static void main(String[] args) throws Exception {\n\n CookieHandler.setDefault(new CookieManager());\n\n HttpCookie sessionCookie = new HttpCookie("session", "53616c7465645f5f9d467d3ae831ec1b1e7289ef45d256224786e1ed13");\n sessionCookie.setPath("/");\n sessionCookie.setVersion(0);\n\n ((CookieManager) CookieHandler.getDefault()).getCookieStore().add(new URI("https://adventofcode.com"),\n sessionCookie);\n\n HttpClient client = HttpClient.newBuilder()\n .cookieHandler(CookieHandler.getDefault())\n .connectTimeout(Duration.ofSeconds(10))\n .build();\n\n HttpRequest req = HttpRequest.newBuilder()\n .uri(URI.create("https://adventofcode.com/2020/day/1/input"))\n .GET().build();\n\n\n System.out.println(client.send(req, HttpResponse.BodyHandlers.ofString()).body());\n\n }\nRun Code Online (Sandbox Code Playgroud)\nsessionCookie.setPath("/"); 重要提示:Java 有 CookieFilter,它实际上匹配请求 URI 路径,而不是 Cookie 路径。
sessionCookie.setVersion(0); 重要提示:此站点不喜欢版本 1(HttpCookie 中的默认值,符合 RFC 2965/2109)
版本 0 符合原始 Netscape cookie,AdventOfCode 喜欢它。
\n版本 0 和版本 1 之间的区别在于 Cookie 的外观:
\n版本0:
\nINFO: HEADERS: HEADERS FRAME (stream=1)\n :authority: adventofcode.com\n :method: GET\n :path: /2020/day/1/input\n :scheme: https\n Cookie: session=53616c7465645f5f9d467....\n User-Agent: Java-http-client/11.0.7\nRun Code Online (Sandbox Code Playgroud)\n版本1:
\nINFO: HEADERS: HEADERS FRAME (stream=1)\n :authority: adventofcode.com\n :method: GET\n :path: /2020/day/1/input\n :scheme: https\n Cookie: $Version="1"\n Cookie: session="53616c7465645f5f9d467.....13";$Path="/"\n User-Agent: Java-http-client/11.0.7\nRun Code Online (Sandbox Code Playgroud)\n版本 1 将从网站抛出 500 服务器错误。
\n为了帮助您调试 HttpClient 日志,请将以下内容添加到程序参数中:
\n-Djdk.httpclient.HttpClient.log=errors,requests,headers,frames[:control:data:window:all],content,ssl,trace,channel,all\nRun Code Online (Sandbox Code Playgroud)\n日志:
\njdk.internal.net.http.HttpClientImpl$SelectorManager run\nINFO: CHANNEL: HttpClient-1-SelectorManager: starting\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.MultiExchange requestFilters\nINFO: MISC: Applying request filters\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.MultiExchange requestFilters\nINFO: MISC: Applying jdk.internal.net.http.AuthenticationFilter@49ec71f8\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.MultiExchange requestFilters\nINFO: MISC: Applying jdk.internal.net.http.RedirectFilter@8f4ea7c\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.MultiExchange requestFilters\nINFO: MISC: Applying jdk.internal.net.http.CookieFilter@436813f3\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.CookieFilter request\nINFO: MISC: Request: adding cookies for https://adventofcode.com/2020/day/1/input\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.MultiExchange requestFilters\nINFO: MISC: All filters applied\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.AbstractAsyncSSLConnection createSSLParameters\nINFO: SSL: AbstractAsyncSSLConnection: Setting application protocols: [h2, http/1.1]\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.AbstractAsyncSSLConnection <init>\nINFO: SSL: SSLParameters:\n cipher: TLS_AES_128_GCM_SHA256\n cipher: TLS_AES_256_GCM_SHA384\n cipher: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384\n cipher: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256\n cipher: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384\n cipher: TLS_RSA_WITH_AES_256_GCM_SHA384\n cipher: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384\n cipher: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384\n cipher: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384\n cipher: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384\n cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256\n cipher: TLS_RSA_WITH_AES_128_GCM_SHA256\n cipher: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256\n cipher: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256\n cipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256\n cipher: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256\n cipher: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384\n cipher: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384\n cipher: TLS_RSA_WITH_AES_256_CBC_SHA256\n cipher: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384\n cipher: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384\n cipher: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256\n cipher: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256\n cipher: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA\n cipher: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA\n cipher: TLS_RSA_WITH_AES_256_CBC_SHA\n cipher: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA\n cipher: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA\n cipher: TLS_DHE_RSA_WITH_AES_256_CBC_SHA\n cipher: TLS_DHE_DSS_WITH_AES_256_CBC_SHA\n cipher: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256\n cipher: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256\n cipher: TLS_RSA_WITH_AES_128_CBC_SHA256\n cipher: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256\n cipher: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256\n cipher: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256\n cipher: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256\n cipher: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA\n cipher: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA\n cipher: TLS_RSA_WITH_AES_128_CBC_SHA\n cipher: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA\n cipher: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA\n cipher: TLS_DHE_RSA_WITH_AES_128_CBC_SHA\n cipher: TLS_DHE_DSS_WITH_AES_128_CBC_SHA\n cipher: TLS_EMPTY_RENEGOTIATION_INFO_SCSV\n application protocol: h2\n application protocol: http/1.1\n protocol: TLSv1.3\n protocol: TLSv1.2\n endpointIdAlg: HTTPS\n server name: type=host_name (0), value=adventofcode.com\n\nnov. 04, 2021 3:35:39 EM jdk.internal.net.http.HttpClientImpl registerTimer\nINFO: MISC: Registering timer ConnectTimerEvent, TimeoutEvent[id=1, duration=PT10S, deadline=2021-11-04T14:35:49.817109800Z]\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription handleSubscribeEvent\nINFO: CHANNEL: Start reading from java.nio.channels.SocketChannel[connected local=/100.120.31.175:57725 remote=adventofcode.com/54.166.48.177:443]\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.SocketTube$InternalWriteSubscriber startSubscription\nINFO: CHANNEL: Start requesting bytes for writing to channel: java.nio.channels.SocketChannel[connected local=/100.120.31.175:57725 remote=adventofcode.com/54.166.48.177:443]\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.HttpClientImpl cancelTimer\nINFO: MISC: Canceling timer ConnectTimerEvent, TimeoutEvent[id=1, duration=PT10S, deadline=2021-11-04T14:35:49.817109800Z]\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection <init>\nINFO: MISC: Connection send window size 65\xc2\xa0535 \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection sendConnectionPreface\nINFO: MISC: /100.120.31.175:57725: start sending connection preface to adventofcode.com/54.166.48.177:443\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection sendConnectionPreface\nINFO: FRAME: OUT: SETTINGS: length=30, streamid=0, flags=0 Settings: HEADER_TABLE_SIZE=16384 ENABLE_PUSH=1 MAX_CONCURRENT_STREAMS=100 INITIAL_WINDOW_SIZE=16777216 MAX_FRAME_SIZE=16384 \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection sendConnectionPreface\nINFO: MISC: PREFACE_BYTES sent\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection sendConnectionPreface\nINFO: MISC: Settings Frame sent\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection sendConnectionPreface\nINFO: CHANNEL: Sending initial connection window update frame: 33\xc2\xa0488\xc2\xa0897 (33\xc2\xa0554\xc2\xa0432 - 65\xc2\xa0535)\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection encodeFrame\nINFO: FRAME: OUT: WINDOW_UPDATE: length=4, streamid=0, flags=0 WindowUpdate: 33488897\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection sendConnectionPreface\nINFO: MISC: finished sending connection preface\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream sendHeadersAsync\nINFO: REQUEST: https://adventofcode.com/2020/day/1/input GET\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection encodeHeaders\nINFO: HEADERS: HEADERS FRAME (stream=1)\n :authority: adventofcode.com\n :method: GET\n :path: /2020/day/1/input\n :scheme: https\n Cookie: session=53616c7465645f5f9d467d3ae831\n User-Agent: Java-http-client/11.0.7\n\n\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection lambda$encodeFrames$9\nINFO: FRAME: OUT: HEADERS: length=126, streamid=1, flags=END_STREAM END_HEADERS \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream getResponseAsync\nINFO: MISC: Response future (stream=1) is: jdk.internal.net.http.common.MinimalFuture@374f597e[Not completed] (id=43)\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection processFrame\nINFO: FRAME: IN: SETTINGS: length=18, streamid=0, flags=0 Settings: MAX_CONCURRENT_STREAMS=128 INITIAL_WINDOW_SIZE=65536 MAX_FRAME_SIZE=16777215 \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection encodeFrame\nINFO: FRAME: OUT: SETTINGS: length=0, streamid=0, flags=ACK Settings: \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection processFrame\nINFO: FRAME: IN: WINDOW_UPDATE: length=4, streamid=0, flags=0 WindowUpdate: 2147418112\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection processFrame\nINFO: FRAME: IN: SETTINGS: length=0, streamid=0, flags=ACK Settings: \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection processFrame\nINFO: FRAME: IN: HEADERS: length=118, streamid=1, flags=END_HEADERS \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): :status: 200\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): date: Thu, 04 Nov 2021 14:35:40 GMT\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): content-type: text/plain\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): content-length: 990\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): server: Apache\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): server-ip: 172.31.16.87\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): vary: Accept-Encoding\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream$HeadersConsumer onDecoded\nINFO: MISC: RECEIVED HEADER (streamid=1): strict-transport-security: max-age=300\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream incoming\nINFO: MISC: handling response (streamid=1)\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream handleResponse\nINFO: HEADERS: RESPONSE HEADERS:\n :status: 200\n content-length: 990\n content-type: text/plain\n date: Thu, 04 Nov 2021 14:35:40 GMT\n server: Apache\n server-ip: 172.31.16.87\n strict-transport-security: max-age=300\n vary: Accept-Encoding\n\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream completeResponse\nINFO: MISC: Completing response (streamid=1): jdk.internal.net.http.common.MinimalFuture@113d2103[Not completed, 1 dependents] (id=42)\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Exchange lambda$wrapForLog$11\nINFO: RESPONSE: (GET https://adventofcode.com/2020/day/1/input) 200 HTTP_2 Local port: 57725\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.MultiExchange responseFilters\nINFO: MISC: Applying response filters\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.MultiExchange responseFilters\nINFO: MISC: Applying jdk.internal.net.http.CookieFilter@436813f3\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.CookieFilter response\nINFO: MISC: Response: processing cookies for https://adventofcode.com/2020/day/1/input\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.CookieFilter response\nINFO: MISC: Response: parsing cookies from {:status=[200], content-length=[990], content-type=[text/plain], date=[Thu, 04 Nov 2021 14:35:40 GMT], server=[Apache], server-ip=[172.31.16.87], strict-transport-security=[max-age=300], vary=[Accept-Encoding]}\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.MultiExchange responseFilters\nINFO: MISC: Applying jdk.internal.net.http.RedirectFilter@8f4ea7c\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.MultiExchange responseFilters\nINFO: MISC: Applying jdk.internal.net.http.AuthenticationFilter@49ec71f8\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.MultiExchange responseFilters\nINFO: MISC: All filters applied\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream readBodyAsync\nINFO: MISC: Reading body on stream 1\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection processFrame\nINFO: FRAME: IN: DATA: length=990, streamid=1, flags=0 \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream schedule\nINFO: MISC: responseSubscriber.onNext 990\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Http2Connection processFrame\nINFO: FRAME: IN: DATA: length=0, streamid=1, flags=END_STREAM \nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream schedule\nINFO: MISC: responseSubscriber.onComplete\n1337\n1906\n2007\n1939\n818\n1556\n2005\n1722\n1484\n1381\n1682\n1253\n1967\n1718\n2002\n1398\n1439\n1689\n1746\n1979\n1985\n1387\n1509\n1566\n1276\n1625\n1853\n882\n1750\n1390\n1731\n1555\n1860\n1675\n1457\n1554\n1506\n1639\n1543\n1849\n1062\n1869\n1769\n1858\n1916\n1504\n1747\n1925\n1275\n1273\n1383\n1816\n1814\n1481\n1649\n1993\n1759\n1949\n1499\n1374\n1613\n1424\n783\n1765\n1576\n1933\n1270\n1844\n1856\n1634\n1261\n1293\n1741\n668\n1573\n1599\n1877\n1474\n1918\n476\n1515\n1029\n202\n1589\n1867\n1503\n1582\n1605\n1557\n587\n1462\n1955\n1806\n1834\n1739\n1343\n1594\n1622\n1972\n1527\n1798\n1719\n1866\n134\n2000\n1992\n1966\n1909\n1340\n1621\n1921\n1256\n1365\n1314\n1748\n1963\n1379\n1627\n1848\n1977\n1917\n1826\n1716\n1631\n1404\n1936\n1677\n1661\n1986\n1997\n1603\n1932\n1780\n1902\n2009\n1257\n1871\n1362\n1662\n1507\n1255\n1539\n1962\n1886\n1513\n1264\n1873\n1700\n807\n1426\n1697\n1698\n1519\n1791\n1240\n1542\n1497\n1761\n1640\n1502\n1770\n1437\n1333\n1805\n1591\n1644\n1420\n1809\n1587\n1421\n1540\n1942\n470\n1940\n1831\n1247\n1632\n1975\n1774\n1919\n1829\n1944\n1553\n1361\n1483\n1995\n1868\n1601\n1552\n1854\n1490\n1855\n1987\n1538\n1389\n1454\n1427\n1686\n1456\n1974\n\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream close\nINFO: MISC: Closing stream 1\nnov. 04, 2021 3:35:40 EM jdk.internal.net.http.Stream close\nINFO: MISC: Stream 1 closed\n\nProcess finished with exit code 0\nRun Code Online (Sandbox Code Playgroud)\nps:弄清楚这真是太有趣了:D
\nJava 11 HttpClient 内置了对 Session-Cookie 的支持。如果您像这样创建客户端:
var client = HttpClient.newBuilder()
.cookieHandler(new CookieManager())
.version(HttpClient.Version.HTTP_2)
.build();
Run Code Online (Sandbox Code Playgroud)
那么客户端会自动保存第一次授权请求中的所有cookie。该客户端发出的任何后续请求都将设置已设置的 cookie。
或者
如果您想在发送初始请求之前为 cookie 设置一些值,请尝试:
var cookieManager = new cookieManager();
cookieManager.getCookieStore().add(someHostURI, someSessionCookie);
//Now this cookie can be used to create the client:
var client = HttpClient.newBuilder()
.cookieHandler(cookieManager)
.version(HttpClient.Version.HTTP_2)
.build();
Run Code Online (Sandbox Code Playgroud)
如需更详细的解释,请查看这篇文章。