当前位置: 首页 > article >正文

Java网络编程 - cookiesession

cookie

之前学习了 Okhttp3 库可以调用API、抓取网页、下载文件。但是这些操作都是不要求登录的,如果 API、网页、文件等内容要求登录才能访问,就需要学习新的 cookie 相关的知识。

下面以豆瓣为例,使用 Java 程序读取“我的豆瓣”页面内容,在此过程中熟悉运用 cookie 。

所谓 cookie ,是存储在客户端浏览器中的一段文本内容。以 key=value (数据名称、数据值)的格式存储一条数据;多条数据之间用分号 ; (英文半角)分开。由于各种浏览器都对 cookie 大小和数量有限制,所以 cookie 目前的核心功能是存储登录数据;额外可以存储一些小数据,比如 是否登录=true;昵称=张三 这样的内容不大的数据。

InternetExplorer 限制 cookie 为每个域名 50 个,上限 4095 个字节。Firefox 每个域名 cookie 限制为 50 个,上限 4097 个字节。每种浏览器略有异同,但肯定都有限制。

1.前期准备

在浏览器输入 https://www.douban.com/mine 打开“我的豆瓣”页面。这个页面是必须登录的。

豆瓣登录

登录完成以后,可以正确看到“我的豆瓣”页面了。

我的豆瓣

注意:登录信息是存放在 cookie 里的

所以,必须先找到登录后的 cookie,这是完成 Java 程序的重要的前提条件。

打开谷歌浏览器的开发者工具(使用谷歌浏览器),切换到 Network 菜单项,如下图:

 对谷歌开发者工具不熟悉的,可以点击查看 使用教程

豆瓣点赞登录

如果没有 mine ,就选第一个跟浏览器地址栏相同的 URL 请求

按照图中所示的四个步骤,把 cookie 的值(Cookie: 后的内容哦,不包括 Cookie:)拷贝下来,放入一个 cookie.txt 文件中。

cookie 的内容很长,而且看不懂。因为 cookie 中除了登录信息,还能放其它信息,大多是加密过的。但没关系,这些信息是给计算机看的。

我们需要编码把 cookie 信息字符串转换为 Map 类型的数据。

3.编码实现

实际上,程序我们前面练习过,就是使用 Okhttp3 库完成 get 请求而已。

上图中可以看到,浏览器在发送请求的时候,自动带上了 HostUser-Agent 内容哦。

这样所需的数据都已识别完毕,我们先看一下演示程序。系统提供了一个工具类,用于从 cookie.txt 文件读取内容。

举例:

Request request = new Request.Builder()
        .url(url)
        .addHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36")
        .addHeader("Referer", "https://www.douban.com/mine")
        .addHeader("Host", "www.douban.com")
        .addHeader("Cookie",ReadFileTool.readContent("cookie.txt"))
        .build();

session

之前已经学会了使用谷歌浏览器的开发者工具抓取到了登录的 cookie ,然后使用程序完成登录。

但 cookie 的弊端是,cookie 是存放在客户端浏览器的,而且是临时的,登录后还想以登录状态与服务器通讯,就比较麻烦。

这就需要在程序中使用 Session 对象来解决这个问题。下面我们通过模拟登录时光网来学会如何应用 Session 对象。

1.时光网登录

浏览器中输入http://www.mtime.com/ 打开时光网,点击右上角的登录按钮;

如果没有看到输入框,可以点击角落电脑图标切换:

弹出登录对话框。

时光网1

或者直接 点此打开注册与登录页面,并点击“会员登录”

时光网2

2.收集信息

然后打开谷歌浏览器的开发者工具,如图所示,Preserve log 必须勾选。

关键点

输入用户名和密码后,在右侧抓取到的网络请求中,找到登录请求 API :

https://front-gateway.mtime.com/user/user/login.api

时光网3

新版浏览器可能有一点不同

在“标头”后面多了一个“载荷”(Payload)的小菜单。

时光网3

切换到小菜单可以看到密码:

时光网3

需要收集的关键信息包括:

  1. 登录地址
  2. 执行方式(GET/POST)
  3. HOST
  4. Referer
  5. User-Agent
  6. 表单数据,数据名称和数据值

3.编码实现

  // 用 CookieJar 实现 cookie 的存储,便于登录后请求其它 URL 可以复用
  private static final OkHttpClient okHttpClient = new OkHttpClient.Builder()
      .cookieJar(new CookieJar() {
        private final HashMap<String, List<Cookie>> cookieStore = new HashMap<>();

        @Override
        public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
          cookieStore.put("mtime.com", cookies);
          System.out.println("[saveFromResponse]url.host()=" + url.host());
        }

        @Override
        public List<Cookie> loadForRequest(HttpUrl url) {
          System.out.println("[loadForRequest]url.host()=" + url.host());
          List<Cookie> cookies = cookieStore.get("mtime.com");
          return cookies != null ? cookies : new ArrayList<>();
        }
      })
      .build();
  • CookieJar 是接口(interface),而 不是 类(class)。演示代码中:

    new CookieJar() {......}
    

    是匿名类。

  • 对表单提交不熟悉的同学,需要复习本课程的第二章第三节。

HashMap

cookieStore 的类型是 HashMap ,相当于一个登录信息的 集合 、 容器 ,可以用来不存 不同域名 的 登录信息(cookie) 。

  • cookieStore.put("mtime.com", cookies); 就是把当前爬取到的时光网的登录信息存储起来。
  • cookieStore.get("mtime.com"); 就是把当前爬取到的时光网的登录信息从容器中拿出来。

当然这个容器是临时的,本质上是存入计算机内存,当前程序关闭掉,信息就消失了

session复用

之前完成了模拟登录,模拟登录的目的,是为了能够调用必须登录的API、或请求必须登录的网页等。其实,为我们只需要在上节课登录成功的基础上,使用 session 对象再次发出请求即可完成这些必须登录的请求。

我们先来看案例演示:请求“个人设置”页面(http://my.mtime.com/personal/personInfo

实现

上一节中把 OkHttpClient 对象进行重构,不再定义为 postContent() 方法的变量。

而是改为类变量:private static final OkHttpClient okHttpClient ,目的就是在整个类中,使用同一个 okHttpClient 执行 HTTP 请求,提升效率。重构在本节课就派上用场了。

分析执行两次请求的过程,实际上过程是类似的,区别是 Request 不同,所以,又做了一次重构,把真正执行的过程封装成一个方法:doExcute ,被其它 postContent() 和 getContent() 方法调用。

这么做就是抽象的过程,目的是减少重复代码,提高可阅读性和可维护性。重构会伴随我们整个编程的生涯。请大家认真体会这个过程,还可以动手试一下,如果不重构,代码会是什么样的?

小知识点

  • static 表示类变量,意味着无论 new 出多少个 PageLoginer 对象,PageLoginer.okHttpClient 都只有一个。
  • final 表示 okHttpClient 一旦第一次 new 出对象后,不能再次 new 新对象

http://www.kler.cn/a/408336.html

相关文章:

  • UE5实现可销毁对象的淡化销毁
  • [SUCTF2019]SignIn
  • 三十一、构建完善微服务——API 网关
  • 企业OA管理系统:Spring Boot技术实现与案例研究
  • 【HAProxy11】企业级反向代理HAProxy高级功能之访问控制列表(ACL)
  • leetcode刷题记录(四十二)——101. 对称二叉树
  • Vulnhub靶场 Jangow: 1.0.1 练习
  • C语言超详细教程
  • 挂壁式空气净化器哪个品牌的质量好?排名top3优秀产品测评分析
  • 网络性能及IO性能测试工具
  • golang实现TCP服务器与客户端的断线自动重连功能
  • 优先算法 —— 双指针系列 - 复写零
  • 青训营刷题笔记17
  • [自动化]获取每次翻页后的页面 URL
  • Java核心特性解析:方法、Stream流、文件与IO详解
  • 每日OJ_牛客_合唱队形_DP_C++_Java
  • 数据库连接池(二)
  • Vue v-if 与 v-for 使用指南:优先级、注意事项及常见错误防范
  • Independent Component Analysis
  • 如何利用ros搭建虚拟场景通过仿真机器人完成一次简单的SLAM建图、导航规划(超简单)?——学习来源:机器人工匠阿杰
  • SpringBoot多文件上传
  • springboot3如何集成knife4j 4.x版本及如何进行API注解
  • Spring集成测试
  • 电子应用设计方案-21:智能取暖系统方案设计
  • C语言之函数的参数
  • C语言:深入理解指针