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

Java网络编程 - headers

User-Agent

之前学习了Okhttp3 库请求网页、API,解析 JSON 格式的结果文本。

但是也不一定任何请求都能成功,例如我们在浏览器中输入 IP 地址详情信息查询的 API :

https://www.done.kim/api/m/service/getIpInfo.php?ip=117.89.35.58&format=json

在浏览器中是可以看到结果的,但是用 Java 程序调用却不行,console 中虽然有结果,但实际上没有需要的内容。因为一些大型网站出于安全等各种因素考虑,会对请求进行比较严格的校验,其中一个重要的校验,是判断请求是否真的来自于一个真实的浏览器。

如果不是来自浏览器,例如 Java 程序请求,API 服务器认为不是真实的浏览器访问,就直接拒绝掉了。

判断请求是否真的来自于一个真实的浏览器,需要从 HTTP 消息头(Headers)中取得 User-Agent 信息后,才能判断。

HTTP header

HTTP 消息头 Headers 是 HTTP 协议的一项重要内容,作用是在发起请求的时候,除了请求参数外,可以附加更多的信息。

Headers 信息并不是写在 URL 中的,属于隐藏的数据,不能直观看到。

User-Agent

User-Agent 是存放在 Headers 中的一种数据信息。作用是在指定 URL 发送请求的时候,告诉服务端当前用户的浏览器类型、版本,甚至操作系统、CPU等非隐私的技术信息

服务器从 Headers 中的 User-Agent 信息获取到浏览器类型、版本等数据后,就认为是一个浏览器请求的环境了,就会给出响应。

所以只要在程序代码中,附加上 User-Agent 信息,就能允许成功了。当然,这里的 User-Agent 是模拟的。

现在模拟一个 win7 + chrome 的环境,User-Agent 的写法如下:

Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1

学以致用

模拟了一个 User-Agent ,程序中怎么用呢?实际上 Okhttp3 库已经支持 Headers 了,只需要在构建 Request 对象的时候,调用 addHeader()方法即可:

Request request = new Request.Builder().url(url).addHeader("User-Agent", "").build();

addHeader() 方法第一个参数是名称,第二个参数是值。

Referer

上节课学习了设置 User-Agent 解决程序请求 HTTP 不成功的情况。实际情况中,还有一类更严格的检查:图片防盗链。

比如下面的图片:

我们可以看到图片无法正常显示,这是因为图片服务器做了“防盗链”。

如何防盗链呢?

因为浏览器在请求网页中的图片(或其它任何文件)时,会自动在 HTTP 消息头 Headers 中,加一个 Referer 信息,表示请求的来源(或者可以理解为图片的上级是网页)。

浏览器自动加“Referer”是业界规范,是默认的行为,不容易干预,即浏览器自动告诉图片服务器,从当前 csdn.com 请求此图片,这时图片服务器拒绝了访问,因为图片服务器的规则是不允许其它网站访问图片。

为什么直接贴网址可以访问?

因为直接拷贝网址、粘贴到浏览器地址栏,就没有“来源”了。此时不是网页中加载图片,而是浏览器直接加载图片,图片没有上级。

浏览器不是上级,浏览器是浏览网页的工具而已。换句话说,“来源”、“上级”指的是访问的具体内容。“User-Agent”就表示用什么样的浏览器工具。

图片服务器允许无 Referer 信息时访问,就可以看到图片了,也就是说,决定权仍然在“图片服务器”,不同公司的服务器规则不同,不能一概而论。浏览器只是收集一些信息提交到服务器,并不能决定是否能看到图片。

程序中的 Referer

为了模拟浏览器自动加 Referer 信息的行为,可以调用语句:

Request request = new Request.Builder().url(url).addHeader("Referer", "https://ham.youkeda.com/course/j14/0").build();

http 响应状态码是:403 时表示禁止访问此图片。

解决办法

贴到浏览器能访问是因为此图片服务器允许无 Referer 信息时访问。但也不是所有图片服务器都允许呢,况且即使同一个图片服务器,也可能修改规则,某一天突然改为必须本站内才能也未可知。为了一劳永逸的解决问题,需要把 Referer 信息设置为图片原始使用的网站。

举例:

public class ImageAsker {/*** 根据输入的url,读取页面内容并返回*/public void getContent(String url) {// okHttpClient 实例OkHttpClient okHttpClient = new OkHttpClient();// 定义一个requestRequest request = new Request.Builder().url(url).addHeader("Refer","http://photo.yupoo.com/").build();try {// 执行请求Response response = okHttpClient.newCall(request).execute();// 打印最终响应的地址String realUrl =  response.request().url().toString();System.out.println("最终响应地址:" +realUrl);// 打印状态码int code = response.code();System.out.println("状态码:" + code);} catch (IOException e) {// 抓取异常System.out.println("request " + url + " error . ");e.printStackTrace();}}public static void main(String[] args) {String url = "http://photo.yupoo.com/vibius/GkRSowXr/medish.jpg";ImageAsker asker = new ImageAsker();asker.getContent(url);}
}

注意上面响应状态码的打印和最终响应的地址。

Host

之前学习了如何使用 Okhttp3 库设置 HTTP 协议的 Headers,以此解决在调用网址、API 过程中可能出现的各种问题。

Host 表示当前请求的域名,虽然这个域名已经存在于 URL 中,但遇到复杂的场景,例如使用代理服务器、或者 URL 中不写域名而是写 IP 地址进行请求等,设置 Host 就非常有用了。

由于 Host 的作用和含义比较宽泛,不能确定各种网站的服务端会拿 Host 做什么,可以有很多作用。所以当前的学习阶段会用就可以了。

跟 User-Agent 和 Referer 一样,Host 也是属于 Headers 数据的字段之一:

Request request = new Request.Builder().url(url).addHeader("Host", "www.douban.com").build();

注意:Host 的值一定是一个域名且不带协议头

在写程序的时候把 Headers 的三个重要信息都写全,这样可以避免很多问题。


http://www.mrgr.cn/news/55150.html

相关文章:

  • 从0开始深度学习(11)——多层感知机
  • Reverse.Kr—— 前四题
  • rabbitmq踩坑(1)
  • 【GAMES101笔记速查——Lecture 14 Ray Tracing2】
  • 技术方向简介
  • 近似推断 - 引言篇
  • YOLOv11模型改进-注意力-引入简单无参数注意力模块SimAM 提升小目标和遮挡检测
  • 华为OD机试 - 贪心歌手 - 动态规划(Python/JS/C/C++ 2024 D卷 200分)
  • 探秘Python读取文件内容的奥秘:从入门到精通
  • 500强企业是如何进行数据安全建设的?看这篇就够了
  • javaspringbootmsyql银行客户管理系统91826-计算机毕业设计项目选题推荐(附源码)
  • 政府采购合同公告明细数据(1996-2024年)
  • AI没必要学
  • 使用上述Python脚本来更新系统环境变量
  • 局域网——Prim Kruskal
  • Python学习100天第14天之网络编程入门和网络应用开发
  • 什么是智能电网?
  • vscode:black formatter配置
  • C++贪心
  • 项目管理的坎坷之路与 MBTI 的启示录
  • VMware ESXi 8.0U3 Huawei (华为) 定制版更新 OEM BIOS 2.7 支持 Windows Server 2025
  • JavaWeb开发5
  • ChatGPT官方桌面客户端的平替,Github 52.7K Stars!支持Mac、Win、Linux!
  • liunx常用基础命令-运维方向
  • LeetCode题练习与总结:区间和的个数--327
  • 面向对象与设计模式第一课:深入理解OOP