前言
網上有很多模擬登陸 LeetCode 的教程,但是基本都是使用 Python 來實現的。作為一個 Java 語言愛好者,因此想用 Java 來實現下。在實現的過程中,也遇到了一些坑點,故在此作為記錄。
過程
根據瀏覽器F12分析登陸頁面




public static final String boundary = "----WebKitFormBoundaryhG2vKxp7y2GAwhPX";
public static final MediaType MULTIPART = MediaType.parse("multipart/form-data; boundary=" + boundary);
String form_data = "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"csrfmiddlewaretoken\"" + "\r\n\r\n"
+ csrftoken + "\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"login\"" + "\r\n\r\n"
+ usrname + "\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"password\"" + "\r\n\r\n"
+ passwd + "\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"next\"" + "\r\n\r\n"
+ "/problems" + "\r\n"
+ "--" + boundary + "--";
RequestBody requestBody = RequestBody.create(MULTIPART,form_data);
複製程式碼
##結果 將其返回的報文列印出來,得到如下資訊則表示模擬登陸成功


程式碼
package LeetCodeLogin;
import okhttp3.*;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import java.io.IOException;
import java.util.*;
import static java.lang.System.out;
public class Login {
public static final String boundary = "----WebKitFormBoundaryhG2vKxp7y2GAwhPX";
public static final MediaType MULTIPART = MediaType.parse("multipart/form-data; boundary=" + boundary);
public static void main(String... args) throws IOException {
Scanner scanner = new Scanner(System.in);
String url = "https://leetcode.com/accounts/login/";
String usrname = "xxx";
String passwd = "xxx";
Connection.Response response1 = Jsoup.connect(url)
.method(Connection.Method.GET)
.execute();
String csrftoken = response1.cookie("csrftoken");
String __cfduid = response1.cookie("__cfduid");
out.println("csrftoken = " + csrftoken);
out.println("__cfduid = " + __cfduid );
OkHttpClient client = new OkHttpClient().newBuilder()
.followRedirects(false)
.followSslRedirects(false)
.build();
String form_data = "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"csrfmiddlewaretoken\"" + "\r\n\r\n"
+ csrftoken + "\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"login\"" + "\r\n\r\n"
+ usrname + "\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"password\"" + "\r\n\r\n"
+ passwd + "\r\n"
+ "--" + boundary + "\r\n"
+ "Content-Disposition: form-data; name=\"next\"" + "\r\n\r\n"
+ "/problems" + "\r\n"
+ "--" + boundary + "--";
RequestBody requestBody = RequestBody.create(MULTIPART,form_data);
Request request = new Request.Builder()
.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary)
.addHeader("Connection","keep-alive")
.addHeader("Accept","*/*")
.addHeader("Origin","https://leetcode.com")
.addHeader("Referer",url)
.addHeader("Cookie","__cfduid=" + __cfduid + ";" + "csrftoken=" + csrftoken)
.post(requestBody)
.url(url)
.build();
Response response = client.newCall(request).execute();
out.println(response.message());
out.println(response.headers());
out.println(response.body().string());
}
}
複製程式碼
需要注意的是,在上述程式碼中,我們通過下述程式碼禁止了重定向,來自己處理重定向請求,可參考使用OkHttp進行重定向攔截處理,若是沒有進行重定向攔截,也會使得模擬登陸失敗。
.followRedirects(false)
.followSslRedirects(false)
複製程式碼
寫在最後
本次模擬登陸,雖然程式碼很簡單,但是確實也經歷了一些波折,比對過 Python 和 Js 寫的模擬登陸的程式碼,用 Java 來進行模擬似乎多了一些瑣碎的細節,對於具體的為何 Python 和 Js 能如此簡介的處理的原理還在琢磨中。此次,也得到了朋友 faberry 的幫助,在一些地方給了意見。