6.HTTP协议
1.定义
HTTP (“超文本传输协议”) 是一种应用非常广泛的应用层协议.
HTTP 往往是基于传输层的 TCP 协议实现的.
2.协议格式
(1)使用Fiddler进行抓包

- 左侧窗口显示了所有的 HTTP请求/响应, 可以选中某个请求查看详情.
- 右侧上方显示了 HTTP 请求的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
- 右侧下方显示了 HTTP 响应的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
(2)HTTP请求

- 首行: [方法] + [url] + [版本]
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
- Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度;
(3)HTTP响应

- 首行: [版本号] + [状态码] + [状态码解释]
- Header: 请求的属性, 冒号分割的键值对;每组属性之间使用\n分隔;遇到空行表示Header部分结束
- Body: 空行后面的内容都是Body. Body允许为空字符串. 如果Body存在, 则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中.
3.HTTP请求
3.1URL
“网址” 其实就是说的 URL (统一资源定位符). 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它

使用Ping命令查看域名对应IP地址

3.2方法
(1)GET方法
- GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源.
- 在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求. 另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求.
- 首行的第一部分为 GET;URL 的 query string 可以为空, 也可以不为空;header 部分有若干个键值对结构;body 部分为空.
(2)POST方法
- POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).
- 通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求.
- 首行的第一部分为 POST,URL 的 query string 一般为空 (也可以不为空),header 部分有若干个键值对结构. body 部分一般不为空. body 内的数据格式通过 header 中的 Content-Type 指定. body 的长度由 header 中的 Content-Length 指定
(3)GET VS POST
- GET 一般用于获取数据, POST 一般用于提交数据.
- GET 的 body 一般为空, 需要传递的数据通过 query string 传递, POST 的 query string 一般为空, 需要传递的数据通过 body 传递
- GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请求是幂等的).
- GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性).
(4)其他方法
- PUT 与 POST 相似,只是具有幂等特性,一般用于更新
- DELETE 删除服务器指定资源
- OPTIONS 返回服务器所支持的请求方法
- HEAD 类似于GET,只不过响应体不返回,只返回响应头
- TRACE 回显服务器端收到的请求,测试的时候会用到这个
- CONNECT 预留,暂无使用
这些方法的 HTTP 请求可以使用 ajax 来构造. (也可以通过一些第三方工具)
任何一个能进行网络编程的语言都可以构造 HTTP 请求. 本质上就是通过 TCP socket 写入一个符
合 HTTP 协议规则的字符串.
3.3请求报头(header)
header 的整体的格式也是 “键值对” 结构,每个键值对占一行. 键和值之间使用分号分割.
- Host :表示服务器主机的地址和端口.
- Content-Length:表示 body 中的数据长度.
- Content-Type:表示请求的 body 中的数据格式
- User-Agent :表示浏览器/操作系统的属性
- Referer:表示这个页面是从哪个页面跳转过来的
- Cookie :存储了一个字符串, 这个数据可能是客户端(网页)自行通过 JS 写入的, 也可能来自于服务器(服务器在 HTTP 响应的 header 中通过 Set-Cookie 字段给浏览器返回数据). 往往可以通过这个字段实现 “身份标识” 的功能
4.HTTP响应
4.1状态码
- 200:OK 表示访问成功
- 404:Not Found 没有找到资源
- 403:Forbidden 表示访问被拒绝
- 405:Method Not Allowed 不允许用户使用一些其他的方法
- 500:Internet Server Error 服务器出现内部错误. 一般是服务器的代码执行过程中遇到了一些特殊情况会产生这个
- 504:Gateway Timeout 当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况
- 302:Move temporarily 临时重定向
- 301:Moved Permanently 永久重定向. 当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址.
4.2响应报头(header)
响应报头的基本格式和请求报头的格式基本一致,类似于 Content-Type , Content-Length 等属性的含义也和请求中的含义一致.
Content-Type响应中的 Content-Type 常见取值有以下几种:
- text/html : body 数据格式是 HTML
- text/css : body 数据格式是 CSS
- application/javascript : body 数据格式是 JavaScript
- application/json : body 数据格式是 JSON
4.3响应正文(body)
正文的具体格式取决于 Content-Type.
5.构造HTTP请求
5.1通过form表单构造
form 的重要参数:
- action: 构造的 HTTP 请求的 URL 是什么.
- method: 构造的 HTTP 请求的 方法 是 GET 还是 POST (form 只支持 GET 和 POST).
<form action="http://abcdef.com/myPath" method="GET"><input type="text" name="userId"><input type="text" name="classId"><input type="submit" value="提交">
</form>
5.2通过ajax构造
(1)发送GET请求
// 1. 创建 XMLHttpRequest 对象
let httpRequest = new XMLHttpRequest();
// 2. 默认异步处理响应. 需要挂在处理响应的回调函数.
httpRequest.onreadystatechange = function () {if (httpRequest.readyState == 4) {console.log(httpRequest.status);console.log(httpRequest.responseText);}
}
// 3. 调用 open 方法设置要访问的 url
httpRequest.open('GET', 'http://42.192.83.143:8080/AjaxMockServer/info');
// 4. 调用 send 方法发送 http 请求
httpRequest.send();
(2)发送POST请求
对于 POST 请求, 需要设置 body 的内容
- 先使用 setRequestHeader 设置 Content-Type
- 再通过 send 的参数设置 body 内容.
// 1. 创建 XMLHttpRequest 对象
let httpRequest = new XMLHttpRequest();
// 2. 默认异步处理响应. 需要挂在处理响应的回调函数.
httpRequest.onreadystatechange = function () {if (httpRequest.readyState == 4) {console.log(httpRequest.status);console.log(httpRequest.responseText);}
}
// 3. 调用 open 方法设置要访问的 url
httpRequest.open('POST', 'http://42.192.83.143:8080/AjaxMockServer/info');
// 4. 调用 setRequestHeader 设置请求头
httpRequest.setRequestHeader('Content-Type', 'application/x-www-formurlencoded');
// 5. 调用 send 方法发送 http 请求
httpRequest.send('name=zhangsan&age=18');
如果是发送json数据
// 4. 调用 setRequestHeader 设置请求头
httpRequest.setRequestHeader('Content-Type', 'application/json');
// 5. 调用 send 方法发送 http 请求
httpRequest.send(JSON.stringify({name: 'zhangsan',age: 18
}));
(3)封装ajax方法
原生的 XMLHTTPRequest 类使用并不方便. 我们可以在这个基础上进行简单封装
// 参数 args 是一个 JS 对象, 里面包含了以下属性
// method: 请求方法
// url: 请求路径
// body: 请求的正文数据
// contentType: 请求正文的格式
// callback: 处理响应的回调函数, 有两个参数, 响应正文和响应的状态码
function ajax(args) {var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (xhr.readyState == 4) {args.callback(xhr.responseText, xhr.status)}}xhr.open(args.method, args.url);if (args.contentType) {xhr.setRequestHeader('Content-type', args.contentType);}if (args.body) {xhr.send(args.body);} else {xhr.send();}
}
// 调用该函数
ajax({method: 'get',url: '/info',callback: function (body, status) {console.log(status);console.log(body);}
});
6.HTTPS
HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层. HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况
HTTPS 就是在 HTTP 的基础上进行了加密, 进一步的来保证用户的信息安全~
6.1理解加密
- 加密就是把 明文 (要传输的信息)进行一系列变换, 生成 密文 .
- 解密就是把 密文 再进行一系列变换, 还原成 明文 .
- 在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为 密钥
6.2工作过程
加密的方式有很多, 但是整体可以分成两大类: 对称加密 和 非对称加密
(1)对称加密
对称加密其实就是通过同一个 “密钥” , 把明文加密成密文, 并且也能把密文解密成明文.
引入对称加密之后, 即使数据被截获, 由于黑客不知道密钥是啥, 因此就无法进行解密, 也就不知道请求的真实内容是啥了
(2)非对称加密
非对称加密要用到两个密钥, 一个叫做 “公钥”, 一个叫做 “私钥”. 公钥和私钥是配对的. 最大的缺点就是运算速度非常慢,比对称加密要慢很多.
- 通过公钥对明文加密, 变成密文;通过私钥对密文解密, 变成明文
- 通过私钥对明文加密, 变成密文;通过公钥对密文解密, 变成明文
客户端在本地生成对称密钥, 通过公钥加密, 发送给服务器. 由于中间的网络设备没有私钥, 即使截获了数据, 也无法还原出内部的原文, 也就无法获取到对称密钥;服务器通过私钥解密, 还原出客户端发送的对称密钥. 并且使用这个对称密钥加密给客户端返回的响应数据. 后续客户端和服务器的通信都只用对称加密即可. 由于该密钥只有客户端和服务器两个主机知道, 其他主机/设备不知道密钥即使截获数据也没有意义.
(3)证书
在客户端和服务器刚一建立连接的时候, 服务器给客户端返回一个证书. 这个证书包含了刚才的公钥, 也包含了网站的身份信息. 这个证书就好比人的身份证, 作为这个网站的身份标识. 搭建一个 HTTPS 网站要在CA机构先申请一个证书;当客户端获取到这个证书之后, 会对证书进行校验
