本文主要是想和大家探讨技术,让大家学会Cookie的使用,切勿做违法之事!

很多Android初学者在刚开始学习的时候,或多或少都想自己搞个应用出来,把自己学的十八般武艺全都用在这个APP上,其实这个想法很好,项目驱动学习,效率更高,这是大学老师教给我的。可是一个APP,如果纯粹搞成一个本地应用,会变得很没有意思,所以我们一般还是做网络应用,网络应用涉及到网络服务器的搭建,数据的采集等等太过于耗时,有的人可能刚刚搭建一个网络服务器就耗费了很长时间,搞得都没有信心学习Android了,针对这种情况,我一般建议大家自己去抓包。抓包又会遇到新问题,就是有可能你需要模拟登陆。因此,本文以知乎登陆为例,带大家来看看模拟登陆,同时也来看看OKHttp中Cookie的使用问题。

为什么选择知乎作为切入点呢?没什么,在想到这个话题的一瞬间刚好想到了知乎!

实际上模拟登陆还是很简单的,麻烦的是需要我们去仔细分析请求的接口和参数!

本文内容主要包括以下三个方面

1.知乎登陆接口和参数分析

2.模拟登陆

3.Cookie持久化

OK,那就开始吧!

1.知乎登陆接口和参数分析

本文采用Chrome浏览器来进行分析,首先打开知乎登录页面,如下:

按下F12,打开Chrome的调试窗口:

然后在知乎的登录页面输入用户名和登录密码,注意观察调试窗口的日志:

在这里我们可以看到传递给服务器的参数主要有如下四个,分别是_xsrf,password,remember_me,以及email四个,remember_me很好理解,是否记住密码,email实际就是我们的账号名称,password实际就是我们的登录密码,至于_xsrf则是登录页面的一个隐藏域,这个数据很容易拿到,同时,从这里我们还可以看出知乎登录时请求的接口是https://www.zhihu.com/login/email。

OK,分析完这些之后,我们就可以动手开始编码了。

2.模拟登陆

知道了知乎在登录的过程中需要传递哪些参数之后,接下来我们就可以动手模拟登录。

用户名、密码以及记住我这三个参数非常容易记忆,很容易获取,之后第一个参数稍微有些麻烦,我们打开用户登录页面的源码,会看到如下一行代码:

这个呢其实就是隐藏域的值。好了,现在登录所需要的四个参数都知道从哪里获取了,那我们就开始登录吧,我的登录页面如下:

输入用户名和密码,点击登录按钮就可以执行登录操作了,但是在执行登录操作之前,我需要先访问知乎的登录页面,拿到那个隐藏域的值。于是乎,我的登录逻辑是这样:

先来看如何获取隐藏域,这里涉及到如何解析HTML文本,我在这里用到了Jsoup库,对该库不了解的小伙伴请自行Google,核心代码如下(完整代码小伙伴们自行在文末下载该Project):

Request request = new Request.Builder().url("https://www.zhihu.com/#signin").build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) { } @Override
public void onResponse(Call call, Response response) throws IOException {
String resp = response.body().string();
Document parse = Jsoup.parse(resp);
Elements select = parse.select("input[type=hidden]");
Element element = select.get(0);
String xsrf = element.attr("value");
Message msg = mHandler.obtainMessage();
msg.what = 1;
msg.obj = xsrf;
Log.d("google_lenve_fb", "onResponse: xsrf:" + xsrf);
mHandler.sendMessage(msg);
}
});

在下载到该HTML文本之后,先将该文本转为一个Document对象,然后使用select选择器,找到有一个属性为type=hidden的input节点,然后获取该节点中的value属性,那么毫无疑问,该value属性,就是我们要得_xsrf的值。有了这个值之后,接下来访问登录页面即可登录成功,代码如下:

FormBody formBody = new FormBody.Builder()
.add("captcha_type", "cn")
.add("_xsrf", xsrf)
.add("password", passwordEt.getText().toString())
.add("remember_me", "true")
.add("email", usernameEt.getText().toString())
.build();
Request request = new Request.Builder().post(formBody).url(loginUrl).build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) { } @Override
public void onResponse(Call call, Response response) throws IOException {
Log.d("google_lenve_fb", "onResponse: " + response.body().string().toString());
}
});

登录成功之后,知乎会返回如下一行Json:

{
"r":0,
"msg":"登录成功"
}

至此为止,我们的模拟登录就成功了,是不是很简单!!!

可是单纯的模拟登录并没有什么意义,举个栗子,我们知道要想获取用户的私信,必须是登录状态才能获取,在知乎中获取用户私信的页面地址是:

https://www.zhihu.com/inbox

可是即使你模拟登录成功了,还是无法获取这个页面的信息,当你访问这个页面的时候,系统会自动跳转到登录页面,因为系统并不知道你已经登录了。那么我该怎么做,才能让系统知道我已经登录成功了呢?这里就涉及到Cookie。

3.Cookie持久化

Cookie这个东西最早由网景的员工在1994年提出,他在他的原始说明文档中解释了Cookie工作原理的基本信息,该文本后来被作为规范纳入到RFC 2965中,网景浏览器从一开始就支持Cookie,现如今所有的Web浏览器都支持Cookie。那么Cookie到底是什么?其实就是浏览器存储在用户电脑上的一小段文本,该文本从何而来?在用户首次登录的时候,服务器会返回一段Cooike文本,浏览器将该文本存入到用户的电脑中,以后每当用户向该服务器发起网络请求时,浏览器都会携带上这段文本,这样服务器就知道该用户是否已经登录过了。

OK,上文是我们对Cookie一个简单的介绍,接下来我们就来看看在我们的OkHttp中如何实现Cookie的缓存。

OkHttp框架从3.0开始简化了Cookie的使用,它提供了一个叫做cookieJar的API,只需要我们实现该API中的方法即可,一个简单的使用方式如下:

builder = new OkHttpClient.Builder();
builder.cookieJar(new CookieJar() {
private final HashMap<String, List<Cookie>> cookieStore = new HashMap<String, List<Cookie>>(); @Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
cookieStore.put(url.host(), cookies);
} @Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = cookieStore.get(url.host());
return cookies != null ? cookies : new ArrayList<Cookie>();
}
});
okHttpClient = builder.build();

该接口中有两个回调方法,一个是保存Cookie,一个是读取Cookie,我将Cookie存储在一个HashMap中,存储和读取都在这个HashMap中操作。设置了Cookie之后,当我再次登录,登录成功之后获取私信时就没有任何问题了。可是存在Map中的东东一旦我的应用退出之后,这个东西就又没了,再次进来还是要登录,那么有什么办法可以实现Cookie的持久化呢?当然可以。Cookie持久化,你可以将Cookie保存 在数据库中,也可以将Cookie保存在SharedPreferences中,都行,我这里以保存在SharedPreferences中,具体代码参考AsyncHttpClient相关类,代码较长,我这里就不贴了,大家可以在文本下载Project,Cookie持久化使用方式如下:

builder = new OkHttpClient.Builder();
CookieJarImpl cookieJarImpl = new CookieJarImpl(new PersistentCookieStore(getApplicationContext()));
builder.cookieJar(cookieJarImpl);
okHttpClient = builder.build();

将Cookie持久化到本地之后,接下来我就可以在登录成功过一次之后,不断的获取私信内容了,如果用户想退出登录,只需要将SharedPreferences中的Cookie信息删除即可,简单吧!

本文所涉及到的工程下载http://download.csdn.net/detail/u012702547/9599322

使用OKHttp模拟登陆知乎,兼谈OKHttp中Cookie的使用!的更多相关文章

  1. Python 爬虫模拟登陆知乎

    在之前写过一篇使用python爬虫爬取电影天堂资源的博客,重点是如何解析页面和提高爬虫的效率.由于电影天堂上的资源获取权限是所有人都一样的,所以不需要进行登录验证操作,写完那篇文章后又花了些时间研究了 ...

  2. python模拟登陆知乎并爬取数据

    一些废话 看了一眼上一篇日志的时间 已然是5个月前的事情了 不禁感叹光阴荏苒其实就是我懒 几周前心血来潮想到用爬虫爬些东西 于是先后先重写了以前写过的求绩点代码 爬了草榴贴图,妹子图网,后来想爬婚恋网 ...

  3. Scrapy 模拟登陆知乎--抓取热点话题

    工具准备 在开始之前,请确保 scrpay 正确安装,手头有一款简洁而强大的浏览器, 若是你有使用 postman 那就更好了.           Python   1 scrapy genspid ...

  4. 使用OkHttp模拟登陆LeetCode

    前言 网上有很多模拟登陆 LeetCode 的教程,但是基本都是使用 Python 来实现的.作为一个 Java 语言爱好者,因此想用 Java 来实现下.在实现的过程中,也遇到了一些坑点,故在此作为 ...

  5. python模拟登陆知乎

    ---恢复内容开始--- 在完成前面的阶段的任务之后,我们现在已经能够尝试着去模拟登录一些网站了.在这里我们模拟登录一下知乎做一下实验.笔者在这里总共用了三天多的时间,下面给大家分享一下笔者是怎么一步 ...

  6. 第十二篇 requests模拟登陆知乎

    了解http常见状态码 可以通过输入错误的密码来找到登陆知乎的post:url 把Headers拉到底部,可以看到form data _xsrf是需要发送的,需要发送给服务端,否则会返回403错误,提 ...

  7. HttpClient 模拟登陆知乎

    最近做爬虫相关工作,我们平时用HttpWebRequest 比较多,每一个Url都要创建一个HttpWebRequest实例, 而且有些网站验证比较复杂,在登陆及后续抓取数据的时候,每次请求需要把上次 ...

  8. python使用requests模块模拟登陆知乎

    from bs4 import BeautifulSoup import requests import time def captcha(captcha_data): with open(" ...

  9. 5-1rquests模拟登陆知乎之httpcode

    1,状态码: 400错误:请求无效 (Bad request);出现这个请求无效报错说明请求没有进入到后台服务里 2,requests库:python常用的库,有空仔细阅读一下官方文档

随机推荐

  1. JAVA线程优化

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  2. IIS UrlWriter配置(asp.net)

    前提在建虚拟目录或网站时注意以下设置第一步:下载URLRewriter 添加URLRewriter和ActionlessForm(不添加只能在VS实现,IIS下会找不到页面). 第二步:配置web.c ...

  3. DP录 (更新)

    补补弱项 全面发展.. 从最基础来 sdut1299最长上升子序 #include <iostream> #include<cstdio> #include<cstrin ...

  4. poj3177

    边双连通有一个非常简单的做法就是先找出所有桥,然后再dfs一次不走桥即可答案是(叶子节点的个数+1)/2 type node=record next,po:longint; end; ..] of n ...

  5. bzoj1069

    四边形的问题可以转化为三角形处理穷举对角线,然后处理上下两个三角形,旋转卡壳 ..] of double; q:..] of longint; l,r,i,j,k,t,n:longint; ans:d ...

  6. 修饰模式(Decorator结构型)C#简单例子

    修饰模式(Decorator结构型)C#简单例子 玩家基本功能是移动.运行等等.BaseAbility新增加功能:1.伤害技能harmAbility:2.阻碍技能BaulkAbility:3.辅助技能 ...

  7. zookeeper使用和原理探究(一)(转)

    zookeeper介绍zookeeper是一个为分布式应用提供一致性服务的软件,它是开源的Hadoop项目中的一个子项目,并且根据google发表的<The Chubby lock servic ...

  8. C# VS2010中,用微软自带的System.Data.OracleClient来连接Oracle数据库

    由于微软在.Net框架4.0中已经决定撤销使用System.Data.OracleClient,造成在VS2010中无法连接Oracle数据库,但它还依旧存在于.Net架构中,我们可以通过自己引用 C ...

  9. [CODEVS3299]有序数组合并求第K大问题

    题目描述 Description 给出两个有序数组A和B(从小到大有序),合并两个有序数组后新数组c也有序,询问c数组中第k大的数 假设不计入输入输出复杂度,你能否给出一个O(logN)的方法? 输入 ...

  10. ARP局域网欺骗工具编写

    每台主机都设有一个ARP高速缓存(ARP cache),里面有本局域网上各主机和路由器的IP地址和硬件地址的映射表,这些都是该主机目前知道的一些地址. 当主机A要向本局域网上的某个主机B发送IP数据报 ...