使用Java和Python连接到会话。HttpURLConnection和CookieManager(Java)。要求(Python)

假设我们需要连接到服务器,登录并支持会话。在浏览器中,它看起来像这样:



  1. 空的GET请求发送到地址http:// localhost:8080 / login
  2. 服务器发送一个表单以填写登录名和密码,还发送一个Cookie,其形式为“ JSESSIONID = 094BC0A489335CF8EE58C8E7846FE49B”。
  3. 填写用户名和密码后,将POST请求发送至服务器,同时发送较早的Cookie,并在输出流中的行“ username = Fox&password = 123”。标头还指定“内容类型:应用程序/ x-www-form-urlencoded”。
  4. 作为响应,服务器向我们发送了一个新的cookie,其中包含新的“ JSESSIONID =”。立即通过带有新Cookie的GET请求将其重定向到http://本地主机:8080 /
  5. 然后,您可以安全地使用服务器API的其余部分,并在每个请求中传递最后一个Cookie。


让我们看看如何用Java和Python来实现。







内容





Python实现。要求



当选择一个库来使用Python使用网络时,大多数站点会推荐request,它充分证明了它的口号:

人类HTTP
整个任务通过以下脚本解决:



import requests
session = requests.session()  # 
url = "http://localhost:8080/login"
session.get(url)   # cookie
data = {"username": "Fox", "password": "123"} 
response = session.post(url, data=data) #


请注意,Cookie和重定向操作在后台进行,就像在浏览器中一样。还应注意,如果创建另一个变量session2,则可以一次保持两个连接处于活动状态。



Java实现,HttpURLConnection和CookieManager



寻找一个用于Java网络的库会一次导致多个库。



例如java.netApache HttpClientOkHttp3



我选择了HttpURLConnection(java.net)。该库的优点是它是一个现成的,并且,如果您需要为android编写应用程序,则可以在官方网站上找到文档缺点是大量的代码。(使用Python之后,这很痛苦。)



所以,让我们开始吧。根据用于会话的文档,可以使用CookieManager



CookieManager cookieManager = new CookieManager(null, CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);


使用这种方法要注意的事项:



  • “ CookiePolicy.ACCEPT_ALL”表示可以使用所有cookie。
  • cookieManager变量将不会在其他任何地方使用。它控制所有连接,并且如果有必要维持多个活动会话,则有必要手动更改此变量中的Cookie。


考虑到这一点,您可以写成一行:



 CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));


第1点和第2点。让我们执行GET请求以获取第一个Cookie:



URL url = new URL("http://localhost:8080/login");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
}


之后,我们的cookieManager将包含来自服务器的cookie,并将在下一个请求中自动替换它。



乐趣始于POST请求。



url = new URL("http://localhost:8080/login");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");


您需要在标题中写“ Content-Type:应用程序/ x-www-form-urlencoded”。



为什么使用getHeaderField方法将该方法称为setRequestProperty而不是setHeaders(或addHeaders)仍然是一个谜。



con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");


接下来是代码,由于某种原因,该代码未隐藏在库的内部。



con.setDoOutput(true);


需要这行代码才能打开传出流。有趣的是,如果没有此行,我们会收到以下消息:



线程“主”中的异常java.net.ProtocolException:如果doOutput = false,则无法写入URLConnection-调用setDoOutput(true)

打开输出流,并在其中输入用户名和密码:



final DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes("username=Fox&password=123");
out.flush();
out.close();


仍然需要从已转发的请求中读取响应。



Java实现,不带CookieManager的HttpURLConnection



您可以在没有CookieManager的情况下实现它,并自己控制Cookie的移动。

第1段和第2段。我们取出cookie。



URL url = new URL("http://localhost:8080/login");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
String cookie = con.getHeaderField("Set-Cookie").split(";")[0];
}


接下来,我们仅通过插入cookie并禁用自动重定向来发送POST请求,因为 在此之前,您需要花一些时间提取新的Cookie:



//  
url = new URL("http://localhost:8080/login");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
// headers  cookie
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Cookie", cookie);
// 
con.setInstanceFollowRedirects(false);
//   
con.setDoOutput(true);
final DataOutputStream out = new DataOutputStream(con.getOutputStream());
out.writeBytes("username=Fox&password=123");
out.flush();
out.close();
//    cookie
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
final StringBuilder content = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
    content.append(inputLine);
String cookie2 = con.getHeaderField("Set-Cookie").split(";")[0];


接下来,我们只需将以下行添加到所有请求中:



con.setRequestProperty("Cookie", cookie2);


希望对您有所帮助。评论中欢迎使用更简单的选项。



All Articles