使用OkHttp模拟登陆LeetCode
前言
网上有很多模拟登陆 LeetCode 的教程,但是基本都是使用 Python 来实现的。作为一个 Java 语言爱好者,因此想用 Java 来实现下。在实现的过程中,也遇到了一些坑点,故在此作为记录。
过程
根据浏览器F12分析登陆页面

从上图可以看出,LeetCode 生成一个 token ,然后在登陆的时候带上这个信息,因此我们模拟登陆的大致思路:首先获取得到 cookie(包含有token),然后在登陆的时候带上这个 cookie 信息,完成 LeetCode 的验证机制,进行模拟登陆。
但是直接进行模拟带上 login(用户名)、password(密码)、csrfmiddlewaretoken(验证信息)是失败的,提示 Forbidden。思考无果,另开思路。
用 fiddler 进行抓包,未登陆状态,数据如下图(也可用浏览器F12来进行分析):

登陆状态,数据如下图,从图中,我们可以发现,其 Content-Type 字段与我们之前常见的值不一样,其是 multipart/form-data 格式,因此我们在模拟登陆,要将其考虑进来。

创建一个 multipart/form-data 的媒体格式,然后生成我们要的请求体,至于我们要的是哪种请求体,其格式可以从 fiddler 抓包的结果获悉。
在SyntaxView中具体的详情如下:

值得注意的是 Content-Type 中的boundary只有四个“-”,而在请求体中有六个“-”,之前因为忽略了这个,一直被拒绝访问(挺坑爹的
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);
结果
将其返回的报文打印出来,得到如下信息则表示模拟登陆成功

从 fiddler 的抓包结果中也可以证实这点

代码
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 的帮助,在一些地方给了意见。
使用OkHttp模拟登陆LeetCode的更多相关文章
- 使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!
本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事! 很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个 ...
- Python 爬虫模拟登陆知乎
在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...
- Python模拟登陆新浪微博
上篇介绍了新浪微博的登陆过程,这节使用Python编写一个模拟登陆的程序.讲解与程序如下: 1.主函数(WeiboMain.py): import urllib2 import cookielib i ...
- PHP 之 CURL 模拟登陆并获取数据
1.CURL模拟登陆的流程和步骤 2.tempnam 创建一个临时文件 3.使用CURL模拟登陆到PHP100论坛 <?php $cookie_file = tempnam('./temp',' ...
- NetworkComms V3 模拟登陆
演示NetworkComms V3的用法 例子很简单 界面如下: 服务器端代码: 开始监听: //服务器开始监听客户端的请求 Connection.StartListening(ConnectionT ...
- pytho简单爬虫_模拟登陆西电流量查询_实现一键查询自己的校园网流量
闲来无事,由于校园内网络是限流量的,查询流量很是频繁,于是萌生了写一个本地脚本进行一键查询自己的剩余流量. 整个部分可以分为三个过程进行: 对登陆时http协议进行分析 利用python进行相关的模拟 ...
- python模拟登陆知乎并爬取数据
一些废话 看了一眼上一篇日志的时间 已然是5个月前的事情了 不禁感叹光阴荏苒其实就是我懒 几周前心血来潮想到用爬虫爬些东西 于是先后先重写了以前写过的求绩点代码 爬了草榴贴图,妹子图网,后来想爬婚恋网 ...
- php模拟登陆的两种实现方法分析
php模拟登陆的实现方法分析 本文实例分析了php模拟登陆的实现方法.分享给大家供大家参考.具体分析如下: php模拟登陆的实现方法,这里分别列举两种方法实现模拟登陆人人网.具体实例代码如下: 1)使 ...
- python 模拟登陆,请求包含cookie信息
需求: 1.通过GET方法,访问URL地址一,传入cookie参数 2.根据地址一返回的uuid,通过POST方法,传入cooki参数 实现思路: 1.理解http的GET和POST差别 (网上有很多 ...
随机推荐
- Codeforces 935 简单几何求圆心 DP快速幂求与逆元
A #include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #def ...
- git初始化第一次拉取线上操作
git: 所有的filename都代表文件名称 一次:git clone 地址 第一步:更新 git pull 第二步:查看修改状态 git status 第三步:根据修改状态查看需要添 ...
- Flutter SDK安装(windows)
Flutter集成了Dart,因此不需要单独安装dart-sdk.Flutter的SDK可以从官网下载:https://flutter.io/sdk-archive/#windows 在Flutter ...
- mysql 分页查询及优化
1.分页查询 select * from table limit startNum,pageSize 或者 select * from table limit pageSize offset star ...
- MySQL--limit使用注意
limit m,n 的意义是在选择.查询得到的结果中,从第m条开始,拿连续的n条作为结果返回.根据它的原理可以知道,select ....limit m,n时要扫描得到的数据条数是m+n条.这就导致m ...
- MySql的导入导出
可以参看之前的博客:https://www.cnblogs.com/shijinglu2018/p/8672699.html 可以参看视频:https://i.cnblogs.com/EditPost ...
- 错误: 找不到或无法加载主类 org.sang.BlogserverApplication
错误: 找不到或无法加载主类 org.sang.BlogserverApplication
- ipcloud上传裁切图片
主页: <!doctype html> <html> <head> <meta charset="utf-8"> <meta ...
- android 后台运行service实现和后台的持续交互
在项目中有这么一种需求 需要后台开启服务,时刻记录用户和软件的交互行为,一旦交互发生,就向服务器测发送一条消息 解决方案: 一.创建一个service服务类 在service中开启一个线程,servi ...
- Linux下开启FTP服务
一.配置步骤 1.安装vsftp 使用yum命令安装vsftp #yum install vsftpd -y 2.添加ftp帐号和目录 先确定nologin的位置,通常在/usr/sbin/nolog ...