您好,欢迎来到九壹网。
搜索
您的当前位置:首页Java网络编程 - headers

Java网络编程 - headers

来源:九壹网

User-Agent

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

https://www.done.kim/api/m/service/getIpInfo.php?ip=117..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; WOW) 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();
    // 定义一个request
    Request 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 的作用和含义比较宽泛,不能确定各种网站的服务端会拿 Host 做什么,可以有很多作用。所以当前的学习阶段会用就可以了。

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

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

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

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

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- 91gzw.com 版权所有 湘ICP备2023023988号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务