8/27 Java学习博客(续)
目前 已经知道了 传输层 UDP/TCP协议 、网络层 IP协议、数据链路层 以太网协议。继续学习应用层的协议 又或者说是一套系统
一、DNS域名解析系统
我们使用IP地址,来描述设备在网络上的位置. 显然IP地址不适合进行宣传.
于是引入了"域名"这样的方式来解决上述问题~~
比如www.baidu.com , 其中 baidu.com便是域名
那我们肯定需要有一套自动的系统,把域名翻译成IP地址.(域名和IP想象成一组键值对)
最早的域名解析系统,是通过一个简单的文件来实现的.
20.205.243.166 github.com
value key
hosts文件来维护域名和ip的映射关系,非常不方便. 于是就有大佬搭建了一套DNS系统(一组服务器)把上述这样的映射关系,保存到这个服务器中了.
如果你想访问某个域名,就先给这个DNS服务器发起请求,查询一下当前域名对应的ip,然后再访问目标网站.
后续如果有域名的更新,只需要更新这一组指定的服务器即可~~不需要修改每个用户电脑的hosts
全世界,无时不刻都有很多设备需要进行DNS的请求.这一组DNS服务器,能抗住这么高的请求量嘛??
一个服务器硬件资源是有限的(CPU,内存,硬盘,网络带宽...)服务器处理每个请求,肯定都是要消耗一定的资源的.
这种所谓的"高并发"问题,
核心思路,就是两条
1.开源
搭建DNS系统的大佬们,就开始号召各个网络运营商,你们都可以自己搭建一组"DNS镜
像服务器",镜像服务器的数据,都从他们这边来同步.
此时用户就会优先访问离自己最近的镜像服务器.
2.节流.让请求量变少.让每个上网的设备,搞本地缓存.
我的电脑1min之内要访问10次www.sogou.com只是让第一次请求DNS即可.把请求得到的结果保存到本地.
后面9次请求都使用第一次的结果即可~~
(域名的变换,没有那么频繁)
HTTP
二、HTTP 协议
使用HTTP协议的场景:
1.浏览器打开网站(基本上) 2.手机APP访问对应的服务器(大概率)
HTTP的报文格式,和前面的TCP/IP/UDP不同 要分两个部分来看待。
即 请求 和 响应
HTTP协议,是一种"一问一答”结构模型的协议.请求和响应的协议格式,是有所差异的~~
============
一问一答(访问网站)
多问一答(上传文件)
一问多答(下载文件)
多问多答(串流/远程桌面)
如何查看到HTTP请求和响应的格式呢?
使用抓包工具~~ 比如 Fiddler 把网卡上经过的数据,获取到,并显示出来~~
HTTP协议是文本格式的协议!!(协议里的内容都是字符串).TCP,UDP,IP....都是二进制格式的协议.
HTTP响应也是文本的.直接查看,往往能看到二进制的数据.(压缩后的)HTTP响应经常会被压缩.压缩之后,体积变小,传输的时候,节省网络带宽.
①请求 分为:
1.首行:
HTTP请求的第一行.有三个部分信息,三个部分使用空格分割.
1)HTTP请求的“方法"(method) 比如GET,POST
2)URL 唯一资源定位符.描述了一个资源在网络上的位置
3)**版本号 **比如 HTTP/1.1
2. 请求头 (header)
是一个键值对结构的数据.(有很多键值对) 每个键值对,都是独占一行的.
键和值之间,使用:空格来区分,这里的键值对都是属于"标准规定"的.
3.空行
请求头的结束标记~~
4正文(body)
有的HTTP请求有,有的没有.
② 响应 分为:
1.首行 :
1)版本号HTTP/1.1
2)状态码(200)描述了请求的结果.
3)状态码描述(OK)
**2. 响应头(header) **
也是键值对结构(有多个键值对)
每个键值对独占一行.
键和值之间使用:空格来区分.
键值对也是"标准规定"的
3.空行
响应头的结束标记~~
4.正文(body)
正文里的内容可能比较长,可能是多种格式.
HTML,CSS,JS, JSON,XML,图片,字体, 视频,音频.....
三、请求中的URL
URL计算机中的非常重要的概念.不仅仅是在HTTP中涉及到.jdbc设置数据源等也有
URL,描述了某个资源在网络上的所属位置.数据库也算是一种“资源”

url中的端口号有时可以省略. 对于http请求,端口号省略,默认是访问80端口
对于https请求,端口号省略,默认是访问443端口
/dir/index.htm? 带层次的文件路径
描述了你要访问服务器的哪个资源(一个服务器提供的资源可能也有很多)
虽然写法是一个看起来像"目录”写法实际上,在服务器中不一定是以目录的形式来存储资源的....
**查询字符串(query string) **是一种键值对结构的数据.以?开头的 键值对之间,使用&来分割.
键和值之间使用=来分割.
一个url中的query string里可以包含N个键值对.甚至可能很长
query string中的键值对都是程序猿"自定义”的.
不像header中的键值对是标准规定的.
(搜狗这里的url的query string里,键值对都是啥意思?咱们作为外人,不懂的.除非你是搜狗的程序猿)
对于query string来说,如果 value 部分要包含一些特殊符号的话,往往需要进行urlencode操作.
?query=C%2B%2B& 表达的是C++
+?😕....这些符号在url中都已经有特殊用途了~
如果在value中,也包含特殊符号,可能就会使浏览器/http服务器,对于url的解析就出现bug
urlencode本质上是一种"转义字符” +的asci就是2B,在前面加上%表示这是转义的结果.
http://陕科大六餐厅:18/熏肉大饼/猪肉熏肉大饼?葱=少放&辣椒=微辣 query string对这次请求进行了补充说明~
**#ch1 片段标识符. **
有的网页内容比较长,就可以分成多个"片段”,通过片段标识符,就可以完成页面内部的跳转
四、GET和POST的区别:
GET 请求,通常会把要传给服务器的数据,加到url的query string中.
POST请求,通常把要传给服务器的数据,加到body中.
这是一种习惯用法.(不是硬性规定,也可以不遵守)

这些HTTP请求,最初的初心,就是为了表示不同的"语义” 在实际的使用过程中,初心,已经被遗忘了.
POST和PUT目前来说,可以理解成没有任何区别!!!(任何使用POST的场景,换成PUT完全可以.反之亦然)
平时一般在谈GET和POST的区别 (经典的面试题)
开篇,先盖棺定论,GET和POST没有本质区别!!!(双方可以替换对方的场景)
虽然没有本质区别,但是在使用习惯上,还是存在一些差异的~~
1.GET经常是把传递给服务器的数据放到query string中;POST 则是经常放到body 中.(使用习惯上最大的差别)
(上述情况并非绝对,GET 也可以使用body,POST 也可以使用query string.使用的前提是客户端/服务器都得按照一样的方式来处理代码)
2.语义上的差异.(虽然语义上HTTP的使用是比较混乱的,但是相比之下,GET和POST还是比较明确的)
GET大多数还是用来获取数据 POST大多数还是用来提交数据(登录+上传)
GET和POST之间的差别,有些说法,需要注意!!!
1.GET请求能传递的数据量有上限,POST传递的数据量没有上限 ❌
早期版本的浏览器(硬件资源非常匮乏),针对GET请求的URL的长度做出了限制.,实际上,RFC标准文档中并没有明确规定 URL能有多长
2.GET 请求传递数据不安全.POST 请求传递数据更安全❌
通常说的"安全”指的是你传递的数据,不容易被黑客获取,或者被黑客获取到之后,不容易被破解
不放在界面上显示,只是忽悠一下小白.对于黑客来说获取成本并不高~~
3.GET只能给服务器传输文本数据.POST可以给服务器传输文本和二进制数据❌
1)GET也不是不能使用body(body中是可以直接放二进制的)
2)GET也可以把二进制的数据进行base64转码,放到url的query string中.
4.GET请求是幂等的.POST请求不是幂等的 √ [不够准确,但是也不是完全错]
吃进去的是草,挤出来的是奶.
如果任何时候吃草,挤出来的都是奶.就是幂等的.
如果吃草之后,不同时候挤出来的东西不一样,就不是幂等的.
GET和POST具体是否是幂等,取决于代码的实现.
GET是否幂等,也不绝对. 只不过RFC标准文档上建议GET请求实现成幂等的
一个典型的GET不幂等的情况:搜狗的广告搜索. 每次进去广告都不一样
5.GET 请求可以被浏览器缓存,POST不可以被缓存 √
(幂等性的延续.如果请求是幂等,自然就可以缓存)
五、认识Header
Header里的键值对是很多的.主要是挑几个重要的介绍一下.
①Host:
Host: www.sogou.com这个信息在url中也是存在的. (在使用代理的情况下,Host 的内容是可能和 url中的内容不同的.)
②Content-Length
body中数据的长度
Content-Type
body中数据的格式
body中的格式,可以选择的方式是非常多的~~
请求:
**1.json ** Content-Type: application/json;charset=UTF-8("username":"tz#18691491410@teacher","password": "Okmfp+ARMQUAST3z63BEMQ==","uuid": "fe4507c3
**2.form表单的格式 ** 相当于是把GET的query string给搬到body中.(后面写个代码来构造)
3.form-data 的格式 上传文件的时候,会涉及到(也不一定就是form-data,也可能是form表单
响应:
1. html Content-Type: text/html; charset=utf-8
2.css Content-Type: text/css
3.js Content-Type: application/javascript; charset=utf-8
4.json Content-Type: application/json;charset=UTF-8
5.图片等等 Content-Type: image/png
后续给服务器提交给请求,不同的Content-Type,服务器处理数据的逻辑是不同的,
服务器返回数据给浏览器,也需要设置合适的Content-Type,
浏览器也会根据不同的Content-Type做出不同的处理
请求里有body,才会有这两个属性. 通常情况下GET请求没有body;POST请求有body.
HTTP在传输层就是基于TCP 的,TCP涉及到粘包问题.使用同一个TCP连接,传输多个HTTP数据包,此时,就会使多个HTTP数据包在TCP接收缓冲区中挨在一起.
接收方解析的时候,就需要能够清楚HTTP数据包之间的边界
对于GET这种没有body 的请求,直接使用空行(分隔符)
对于 POST这种有body 的请求,就结合空行和Content-Length
③User-Agent (简称 UA)
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64:; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537. 36
UA描述了你使用啥设备上网.
开始时候,网页非常简单,就只是一些单纯的文字.浏览器功能也比较原始,后来,网页内容越来越丰富了,浏览器的功能也开始逐渐升级.这个升级过程也是很快的.(新的浏览器出现的很快)
新的浏览器诞生之后,并不是立即就占据全部市场.相当一部分时间里
新浏览器和旧浏览器,并存的.
网站的开发者就遇到困难了,开发者就需要考虑到,是否要兼容旧版本浏览器?
事实上,可以使用 User-Agent来进行区分的,UA中记录了浏览器的版本.哪个版本的浏览器都支持哪些特性,是容易获取的.
**④Referer 描述了当前页面是从哪个页面跳转来的. **
⑤Cookie Cookie 可以认为是浏览器在本地存储数据的一种机制.
浏览器的数据来自于服务器.浏览器后续的操作也是要提交给服务器的.
服务器这边管理了一个网站的各种核心数据
但是程序运行过程中,也会有一些数据,需要在浏览器这边存储的.并且在后续请求的时候数据可能需要再发给服务器
上次登陆时间.上次访问时间.用户的身份信息.累计的访问次数...
临时性的数据.
存储在浏览器比较合适的.
实际上更容易想到的是,把这样的数据直接存储到本地文件中,但是实际上不可行的.浏览器为了考虑到安全性,禁止网页直接访问你的电脑的文件系统,网页代码中也就无法直接生成一个硬盘的文件来存储数据了.
为了保证安全性,又能进行存储数据,于是就引入了Cookie(也是按照硬盘文件的方式保存的,但是浏览器把操作文件给封装了.
网页只能往Cookie中存储键值对
Cookie是按照键值对的形式来组织的. 键值对之间,使用;分割.键和值使用=分割.
这里的键值对也都是程序猿自定义的(和query string差不多)
后续再请求这个服务器的时候,就会把Cookie中的内容自动代入到请求中,发给服务器.服务器通过Cookie的内容做一些逻辑上的处理.
六、响应状态码
表示了这次请求对应的响应,是啥样的状态(成功,失败,其他的情况.对应的原因是啥..)
①2xx都表示成功.
200最常见的.
②3xx表示重定向. 请求中访问的是A这样的地址.响应返回了一个重定向报文,告诉你应该要访问B地址
很多时候,页面跳转,就可以通过重定向来实现.还有的时候,某个网站,服务器迁移了.(IP/域名变了)就可以给旧的地址挂一个重定向响应.
重定向的响应报文中,会带有Location字段描述出当前要跳转到哪个新的地址.
③404 Not Found 请求中访问的资源,在服务器上不存在
**④ 403 Forbidden **表示访问的资源没有权限
**⑤5xx **表示服务器出错了
键值对HTTP中存在很多种键值对
- query string
- header
- cookie
- body
form key1=value1&key2=value2
json { key1: value1, key2: value2)
进行编程的时候,很多时候都是在拿着这些键值对做文章.
以上,是HTTP协议报文结构的基本情况.
七、如何让客户端构造一个HTTP请求
浏览器
1.直接在浏览器地址栏输入url,此时构造了一个GET请求.
2.html 中,一些特殊的html标签,可能会触发GET请求.
像 img, a, link, script ...
3.通过form表单来触发GET/POST请求
(咱们需要了解一下)
form本质也是一个HTML标签~~
这里写一个简单的html代码,来编写逻辑~ 如图先认识下


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
Title
</head>
<body>
<form action="网页链接 method="get">
<input type="text" name="key1">
<input type="text" name="key2">
<input type="text" name="key3">
method属性描述了当前要构造的请求是 get 还是 post.
form只支持 get和post,不支持其他的http方法.
<input type="text" name="key1">
构建了个输入框
输入框中的内容就会被构造成http请求的query string
(query string是键值对.其中 key 就是 input 输入框的 name 属性, value 就是输入框中用户输入的内容)
<input type="submit" name="提交">
做了一个提交
当前已经把请求构造出来了.很明显,当前得到的响应是404.要想有一个正确的响应,往往需要服务器这边的代码配合
框中分别输入1,2,3 构建出来的 key1=1&key2=2&key3=3 对于GET来说,这几个键值对,是在url中.
对于 POST来说,这几个键值对,就在body中了.
4.ajax的方式
form有一些缺陷.只支持GET和POST,不支持其他方法.form会触发页面跳转.(有的
时候不想跳转) ajax.通过js提供的api来构造http请求
HTTPS
当前网络上,主要都是HTTPS了,很少能见到HTTP.
实际上HTTPS也是基于HTTP.(前面讲过的HTTP的各个方面的内容,对于HTTPS同样适用)
只不过HTTPS在HTTP的基础之上,引入了"加密"机制.
引入HTTPS防止你的数据被黑客篡改(尤其是反针对运营商劫持)
八、加密
1.对称加密.
加密和解密,使用的密钥是同一个密钥.
设密钥为key
明文+key=>密文
密文+key=>明文
2.非对称加密.有两个密钥(一对) 、
这俩密钥,一个称为"公钥”,一个称为"私钥”(公钥就是可以公开的,私钥就是自己藏好的)
明文+公钥=>密文
密文+私钥=>明文
或者
明文+私钥=>密文
密文+公钥=>明文
也叫签名(证书会用到)
HTTPS的工作过程.目标,针对HTTP这里的header和body进行加密~~
1.先引入对称加密~~
客户端使用密钥进行对称加密,通过路由器转发到服务器,服务器拿着同一个密钥进行解密。
黑客入侵了路由器,没有密钥。截获了请求内容也无法解密。
当前上面的模型存在一个重要问题.
服务器不是只和一个客户端通信,而是和很多客户端通信.这些客户端使用的对称密钥是相同的嘛?
很明显,必须要求每个客户端的密钥都不相同.彼此之间才不知道对方的密钥是啥
此时要求每个客户端对应的密钥都不同
现在就需要每个客户端,在和服务器建立连接的时候,就把密钥给生成出来(涉及到一些随机数机制在里面,保证每个客户端生成的密钥都不同)
客户端再把自己的密钥通过网络传输给服务器.
**如果密钥被黑客截获了,这不也就凉了?? **
此时,黑客知道了通信的密钥.后续传输的加密数据,黑客就可以很轻松的进行解密~ 此时的加密过程,形同虚设~
所以我们就引入非对称加密来防止这个情况发生。
**客户端先找服务器要公钥 然后再用公钥加密客户端自己的密钥 **
然后把加密后的客户端密钥发过去,服务器在用私钥解密,然后服务器获取到客户端的密钥了,
接着 二者就用客户端的密钥进行传输
既然已经引入了非对称加密,为啥还需要引入对称加密呢?
直接使用非对称加密,来完成所有业务数据的加密传输即可.
需要知道 对称加密,运算成本低,速度快
进行非对称加密/解密,运算成本是比较高的.运算速度也是比较低的.
使用非对称加密,只是用来进行这种关键环节(传输密钥)(一次性的工作,体积也不大),成本就比较可控,
后续要传输大量的业务数据,都使用效率更高的对称加密,比较友好的做法.如果业务数据都使用非对称加密,整体的传输效率就会大打折扣了.
!!!引入安全性,引入加密,也势必会影响到传输效率.我们也是希望让这样的影响能尽可能降到最低~~
上述对称加密+非对称加密过程就是HTTPS的基本盘~~ 但是光有这些还不够.上述流程中还存在一个严重的漏洞,黑客如果利用好这个漏洞,仍然可以获取到原始的明文数据~~~
九、中间人攻击
服务器就提前生成好了一对公钥(pub1)和私钥(pri1)
客户端向服务器申请 公钥
服务器返回了pub1 这时被黑客截获
黑客给客户端返回一个它自己的pub2
客户端不知道pub2是黑客的以为就是服务器的呢~~于是就使用pub2针对 对 对称密钥 进行加密了.
然后再把这个传给服务器,黑客此时就截获到了pub2加密的 对称密钥,获取后,需要使用pri2解密.黑客手里当然有pri2(他自己生成的),黑客解密之后,拿到了对称密钥.
并且使用服务器刚才的pub1重新对对称密钥加密,进一步的发送给服务器.
服务器收到数据之后,使用pri1进行解密这个解密是完全能够成功的. 所以服务器和客户端此时并不知道有中间人的存在
由于对称密钥,黑客在刚才的过程中,已经拿到了.所以此时加密传输的数据对于黑客来说已经一览无余了.
如何解决上述 中间人攻击问题呢?? 之所以能进行中间人攻击,关键要点在于客户端没有"分辨能力"客户端不知道当前这个公钥是不是黑客伪造的!!!
这里的"分辨"不能靠"自证"(谁都是说自己是真的)
我们就引入第三方的可以被大家都信任的"公证机构” 公证机构说这个公钥是正确的,不是被伪造的,我们就是可以信任的~~
服务器 向公证机构提出申请.(提交一些材料域名,公钥,厂商...)
公证机构 公证机构就会对这些材料进行审核.审核通过就会给服务器颁发一个"证书"
计算机中的"证书"就是一段结构化的数据.这段数据中就会包含一些重要的信息.
比如,
网站的域名
服务器的公钥
证书的过期时间。
数字签名(*)
然后客户端请求的就不是公钥而是证书,客户端拿到了证书,也就拿到了证书中的公钥~~
客户端就需要验证这个公钥是否是服务器最初的公钥(是否是被黑客篡改了??)
这个过程,就称为"证书的校验”
如何进行校验?核心机制,就是“数字签名"=>被加密后的校验和
颁发证书的时候,公证机构,就会针对证。书中的各个属性,计算出一个校验和,并且针对这个校验和进行加密,就得到了数字签名.
这个加密,也是非对称加密。公证机构,自己生成一对公钥和私钥(和服务器的公钥私钥不一样)
公证机构就会自己持有私钥.公钥就会发布给各个客户端设备(往往公钥都是内置到系统中的.安装了操作系统,就会自带公证机构的公钥)
就是这个
明文+私钥=>密文
**密文+公钥=>明文 **
此时,客户端拿到了数字签名,就可以通过系统内置的公证机构的公钥,进行解密了.得到了最初的校验和.
客户端再 重新 计算一遍 这里的校验和,和解密出来的校验和进行对比,如果校验和一致,就可以认为证书没有被篡改过,
那么黑客替换公钥之后,能否自己替换掉数字签名,自己算一个呢??
不能的!!!针对校验和加密,需要使用公证机构的私钥,才能进行的.
黑客没有这个私钥.如果黑客拿自己的私钥加密,客户端也就无法使用公证机构的公钥解密了
公证机构的公钥是客户端系统自带的,黑客也无法替换....
结合上述过程,证书就是可信的.通过了校验,就说明公钥就是服务器原始的公钥了.
总结:
https加密:
1)对称加密,加密业务数据
2)非对称加密,加密对称密钥 1和2相结合,保证最终https的安全性了.
3)中间人攻击
4)使用证书,校验服务器的公钥

浙公网安备 33010602011771号