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
中虽然有结果,但实际上没有需要的内容。
这是因为像 taobao.com
这样的大型网站,处于安全等各种因素考虑,会对请求进行比较严格的校验,其中一个重要的校验,是判断请求是否真的来自于一个真实的浏览器。
如果不是来自浏览器,例如 Java
程序请求,API
服务器认为不是真实的浏览器访问,就直接拒绝掉了。
判断请求是否真的来自于一个真实的浏览器,需要从 HTTP
消息头(Headers
)中取得 User-Agent
信息后,才能判断。
HTTP header
HTTP
消息头 Headers
是 HTTP
协议的一项重要内容,作用是在发起请求的时候,除了请求参数
外,可以附加更多的信息。
关于
Headers
的更多资料,属于课外阅读的知识,感兴趣的同学可以点击链接阅读 HTTP Headers文档
这里只要记住,Headers
信息并不是写在 URL
中的,属于隐藏的数据,不能直观看到。
User-Agent
User-Agent
是存放在 Headers
中的一种数据信息。作用是,在指定 URL
发送请求的时候,告诉服务端当前用户的浏览器类型、版本,甚至操作系统、CPU等非隐私的技术信息
。
服务器从 Headers
中的 User-Agent
信息获取到浏览器类型、版本等数据后,就认为是一个浏览器请求的环境了,就会给出响应。
关于
User-Agent
的详细资料,属于课外阅读的知识,感兴趣的同学可以点击链接阅读 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()
方法第一个参数是名称,第二个参数是值。
在 console
中已经打印了响应的结果。
Referer
上节课学习了设置 User-Agent
解决程序请求 HTTP
不成功的情况。实际情况中,还有一类更严格的检查:图片防盗链。
例如下列图片:
我们可以看到,图片无法正常显示,因为图片服务器做了“防盗链”。
图片网址是:https://cdn.nlark.com/yuque/0/2019/png/93870/1571386626984-2462f7f9-d397-4e50-91e4-e4b688dd3410.png
大家拷贝图片网址贴到浏览器地址栏,是可以访问的。
如何防盗链呢?
因为浏览器在请求网页中的图片(或其它任何文件)时,会自动在 HTTP
消息头 Headers
中,加一个 Referer
信息,表示请求的来源(或者可以理解为图片的上级是网页)。
浏览器自动加“Referer”是业界规范,是默认的行为,不容易干预
即浏览器自动告诉图片服务器,从当前 youkeda.com
请求此图片,这时图片服务器拒绝了访问,因为图片服务器的规则是不允许其它网站(非nlark.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
信息设置为图片原始使用的网站。
程序中如何知道 Referer 值?
在本课程后面的章节中,会教大家使用 工具 查找Referer值。大家稍安勿躁,当前的重点是理解Referer的作用,并且熟练完成程序。
Host
前两节我们学习了如何使用 Okhttp3
库设置 HTTP
协议的 Headers
,以此解决在调用网址、API
过程中可能出现的各种问题。
这节课学习 Host
,也是 Headers
中非常重要的信息之一。
Host
表示当前请求的域名。虽然这个域名已经存在于 URL
中,但遇到复杂的场景,例如使用代理服务器、或者 URL
中不写域名而是写 IP
地址进行请求等,设置 Host
就非常有用了。
由于 Host
的作用和含义比较宽泛,就不能确定各种网站的服务端会拿 Host
做什么,可以有很多作用。所以当前的学习阶段会用就可以了。
关于
Host
的详细资料,属于课外阅读的知识,感兴趣的同学可以点击链接阅读 Host文档
跟 User-Agent
和 Referer
一样,Host
也是属于 Headers
数据的字段之一:
Request request = new Request.Builder()
.url(url)
.addHeader("Host", "www.douban.com")
.build();
注意,Host
的值一定是一个域名且不带协议头。
即使目前大家还不太能明白 Host
的具体作用也没关系,大家在写程序的时候,要把 Headers
的三个重要信息都写全,这样可以避免很多问题。