- 空的GET请求发送到地址http:// localhost:8080 / login。
- 服务器发送一个表单以填写登录名和密码,还发送一个Cookie,其形式为“ JSESSIONID = 094BC0A489335CF8EE58C8E7846FE49B”。
- 填写用户名和密码后,将POST请求发送至服务器,同时发送较早的Cookie,并在输出流中的行“ username = Fox&password = 123”。标头还指定“内容类型:应用程序/ x-www-form-urlencoded”。
- 作为响应,服务器向我们发送了一个新的cookie,其中包含新的“ JSESSIONID =”。立即通过带有新Cookie的GET请求将其重定向到http://本地主机:8080 /。
- 然后,您可以安全地使用服务器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.net,Apache HttpClient和OkHttp3。
我选择了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);
希望对您有所帮助。评论中欢迎使用更简单的选项。