HTTP协议介绍

目录

前言

一、概述

[1. HTTP 协议](#1. HTTP 协议)

[2. Fiddler](#2. Fiddler)

[3. 协议格式](#3. 协议格式)

[1. HTTP 请求](#1. HTTP 请求)

[2. HTTP 响应](#2. HTTP 响应)

[4. URL](#4. URL)

二、协议解析

[1. 方法](#1. 方法)

[2. 请求/响应头](#2. 请求/响应头)

[3. 常见状态码](#3. 常见状态码)

[三、构造 HTTP 请求](#三、构造 HTTP 请求)

[1. 使用 Postman](#1. 使用 Postman)

[2. 调用SocketAPI](#2. 调用SocketAPI)

[3. html 和 js](#3. html 和 js)

四、HTTPS

[1. 基本概念](#1. 基本概念)

[2. 对称加密](#2. 对称加密)

[3. 非对称加密](#3. 非对称加密)

[4. 中间人攻击](#4. 中间人攻击)

[5. 公证机构](#5. 公证机构)


前言

本文系统介绍了HTTP协议及其相关技术要点。主要内容包括:1. HTTP协议概述:解释了HTTP协议的基本特性、交互过程及Fiddler抓包工具的使用方法;2. 协议格式解析:详细说明了HTTP请求和响应的四部分结构(首行、头、空行、正文)及URL的组成要素;3. GET/POST方法对比:澄清了常见误解,强调两者本质区别在于使用习惯而非安全性;4. 状态码和头部字段:列举了常见状态码含义及Cookie等重要头部字段的作用机制;5. 请求构造方式:介绍了Postman工具及Socket API实现方法;6. HTTPS加密机制:阐述了对称/非对称加密原理、SSL握手过程及中间人攻击防范措施。文章全面覆盖了HTTP/HTTPS协议的核心概念和应用场景。


一、 概述

1. HTTP 协议

HTTP 协议是一个超文本传输协议,不仅仅可以携带字符串,还可以携带图片,html 等特殊格式;

HTTP 协议目前广泛使用的版本仍然是 HTTP/1.0;

HTTP/1.0 是基于 TCP 协议的;

HTTP 最主要的应用场景是网站,用于客户端和服务器之间传输数据;

HTTP 的交互过程是典型的"一问一答",客户端不请求,服务器是不能主动给客户端发消息的;

2. Fiddler

HTTP 协议的报文,可以使用 Fiddler 进行抓包;

Fiddler 本质上是一个客户端代理;

客户端把请求发给代理,代理再把请求发给服务器; 服务器返回响应给代理,代理再把响应发给客户端;

代理有客户端代理,也有服务器代理;客户端代理也叫正向代理,服务器代理也叫反向代理;

打开网站的过程:

  1. 打开网站,客户端和服务器之间进行交互,不是只有一次,通常都会有很多次;
  2. 客户端和服务器第一次交互,是拿到页面的 html;
  3. html 还会依赖 css和 js,html 被浏览器加载之后,又会触发其它的 http 请求,获取 css 和 js 等;
  4. 当执行到 js,又会触发一些 http 请求,获取到数据;

在 Fiddler 中,蓝色的报文往往表示返回的是一个 html,往往是访问网站的入口请求;

双击报文,可以看到明细,上面的是请求,下面的是响应,点击 Raw 可以看到原始数据,也可以点击 View in Notepad 在记事本中查看:

如果响应中出现乱码,是因为为了节省带宽,将响应中的正文压缩了;

可以点击 Response body is encoded. Click to decode 解压,显示就正常了;

3. 协议格式

1. HTTP 请求

HTTP 请求中包含四个部分:首行,请求头,空行,正文(body);

首行:包括方法,URL 和 协议版本号;

请求头:

包含多个键值对,这些键值对是 HTTP 协议中定义的;

键值对之间使用换行分割,键和值之间使用冒号空格分割;

空行:表示请求头结束

正文(body):

就是 http 协议的载荷,有的请求有正文,有的没有;

正文的可以是各种格式,例如:json;

2. HTTP 响应

HTTP响应中也包含四个部分:首行,响应头,空行,正文(body);

首行:

也包含三个部分:协议版本号,状态码,和状态码描述;

响应头:

同请求头;

空行:表示响应头结束;

正文(body):可以是各种格式,例如 html,json等;

4. URL

用于描述一个网络上资源的位置;

网络上的资源位置是如何描述的:

  1. 通过 IP 地址,知道服务器的位置;
  2. 通过端口号知道进程;
  3. 通过带层次的文件路径知道具体资源的位置;

URL 可以用于 HTTP 协议,也可以用于其它协议;

以下面 URL 为例:

http://user:pass@www.example.com:80/dir/index.html?uid=1\&name=1#ch1

URL 包括:协议方案名,登录信息,域名或者 IP 地址,端口号,带层次的文件路径,查询字符串和片段表示符;

登录认证信息:

写在 URL 中并不安全,因此基本不在 URL 中写了;

IP 地址:

写域名或者 IP 地址都可以;

端口号:

如果不写端口号,就会使用默认端口号,http 协议的默认端口号是 80,https 的默认端口号是 443;

查询字符串:

是给服务器传递信息的重要途经,也是按照键值对组织的,通过 ?开始,键值对之间使用 & 分割,键和值使用 = 分割;

查询字符串中键值对是程序员自定义的;

片段标识符:

用来分割页面的某个部分,通过片段表示可以完成页面内跳转;

URL encode:

在 URL 中 /,:,?,&,@ 等符号都是具有特殊含义的;

在查询字符串里面使用键值对,如果想使用特殊符号,汉字或者其它语言,应该进行转义;

转义的方式是通过 % 加上字符在 UTF8 码表中的编码值的 16 进制表示;

例如:

https://www.baidu.com/s?wd=%E9%98%B3%E5%85%89%E7%8E%AB%E7%91%B0%E5%9B%A0%E4%BD%95%E8%B7%8C%E6%88%90%E2%80%9C%E5%9C%B0%E6%9D%BF%E4%BB%B7%E2%80%9D&sa=fyb_n_homepage&rsv_dl=fyb_n_homepage&from=

真实的 URL 中是没有汉字的,而是使用了转义的方式:

二、协议解析

1. 方法

http 协议中使用最多的方法是 GET 和 POST;

GET 操作可以理解为从服务器获取资源,也叫做读操作;

POST 操作可以理解为向服务器传输内容,也叫做写操作,常用于登录和上传;

GET 和 POST 的区别:

  1. GET 和 POST 本质上没有区别,可以互相替换;
  2. 在使用习惯上,GET 习惯于把数据放到 URL 的查询字符串中,POST 习惯于把数据放到正文中;实际上 GET 也可以把数据放到正文中,POST 也可以把数据放到查询字符串中;
  3. 语义上 GET 是用来从服务器获取数据,POST 是给服务器传输数据;
  4. 关于幂等性,标准文档建议 GET 实现成幂等的,POST 则无要求;幂等指的是输入内容一定,输出结果也一定;

关于 POST 和 GET 的错误说法:

    1. POST 比 GET 更安全,登录的时候如果使用 GET,用户名和密码就会显示在 URL 上;
  • 如果使用明文传输,不管是 GET 方法,还是 POST 方法,只要通过抓包,都可以获取用户名和密码,本质上这都是不安全的,不存在 POST 比 GET 更安全的说法;
  • 安全的实现关键在于加密,加密做的好,放在 URL 或者正文中,都不容易被破解,都是安全的;
    1. GET 的数据传输量小,POST 的数据传输量大;
  • GET 虽然习惯于把传输的数据放在查询字符串中,但是 URL 的长度本身是没有限制的,因此 GET 可以把放在正文传输的数据都放在 URL 中,POST 比 GET 传输数据量大的说法不成立;
    1. GET 只能携带文本数据,POST 能携带二进制数据;
  • 虽然 URL 中只能携带文本数据,但是可以对二进制数据进行 urlencode,转化成文本,服务器接收到再进行 urldecode,就能将文本还原成二进制数据;
  • POST 请求中虽然经常携带二进制数据,但也不是直接携带,也是通过 urlencode 或者 base64 转码成文本数据;

2. 请求/响应头

**Host:**表示服务器的主机和端口;虽然 url 中已经有 IP 地址和端口号了,并且绝大部分都是相同的,但是也存在 Host 和 url 中不相同的情况;

**Content-Length:**http 协议的底层也是 TCP,接收方的缓存区中数据会连在一起,因此也存在粘包问题。使用这个长度就可以知道正文中的内容占多少字节,明确包之间的边界,解决粘包问题;

**Content-Type:**表示正文中的数据格式;

请求中常见的格式:

  1. application/json;
  2. application/x-www-form-urlencoded,也称为 form 表单;
  3. mutipart/form-data,上的文件需要用到;

响应中常见的格式:

  1. text/plain 纯文本;
  2. text/html;
  3. text/css;
  4. application/javascript;
  5. application/json;
  6. img/png;
  7. img/jpg;

浏览器和服务器交互时,为了提高效率,会把不变的内容在浏览器本地的硬盘上进行缓存,后续再向服务器请求就会直接读本地的,减小网络开销;

调试时,经常通过 ctrl+F5 的方式清除缓存;

**User-Agent(简称 UA):**描述了操作系统和浏览器的信息;根据用户的操作系统和浏览器的信息,给用户展示不同的排版;

**Referer:**描述了页面是从哪里跳转的;

直接输入 URL 和从收藏夹打开,是没有 Referer 的,从其它网站跳转过来,就会有 Referer;

**Cookie:**本质上是浏览器本地持久化存储数据的机制;

为了保证用户数据安全,浏览器不允许网页直接调用浏览器的 API 去操作用户的数据;

而是给网页提供了一些 API,可以让网页有限度的操作,而不允许随意访问用户的文件系统;

Cookie 是键值对格式的,是程序员自定义的;

http 请求中的 Cookie 字段,就是把本地存储的 Cookie 信息,发送给服务器;

http 响应中可以有 Set-Cookie 字段,就是让浏览器在本地保存这个字段保存成 Cookie;

Cookie 的重要结论:

  1. 从哪里来:Cookie 是服务器返回给浏览器的,通常是首次访问或者登录之后;
  2. 到哪里去:Cookie 会存在浏览器本地的硬盘上,后续每次访问服务器,都会带上 Cookie;不同的客户端保存的 Cookie 是不同的;
  3. 存什么:Cookie 中存的是键值对格式的数据,内容是程序员自定义的;
  4. 在浏览器中如何组织:Cookie 在硬盘本地保存,按照不同的域名分别存储;
  5. 用途是什么:Cookie 的主要用途是在客户端保存数据,经常用来保存用户的身份标识,通过身份标识,找到服务器中存储的业务数据;业务数据不会保存在 Cookie 中,因为 Cookie 很容易被删除;

3. 常见状态码

    1. 200 OK,表示请求成功;
    1. 404 Not Found,表示访问的资源没找到;
    1. 403 Forbidden,请求的资源没有权限访问;
    1. 405 Method Not Allowed,服务器不支持这个方法;
    1. 500 Internal Server Error,服务器内部错误;
    1. 504 Gateway Timeout,访问服务器超时;
    1. 302 Move Temporarily,临时重定向;
    1. 301 Move Permanently,永久重定向;

301 和 302 会影响浏览器的缓存:

如果是 301,表示永久重定向,浏览器会把重定向的地址缓存下来,后续继续访问直接访问重定向的地址即可,不需要再跳转;

如果是 302,表示临时重定向,浏览器不会缓存重定向的地址;

三、构造 HTTP 请求

1. 使用 Postman

Postman 界面如下:

可以选择要使用的方法,方法后面写 URL;

Params 指的是 url 中的查询字符串;

Headers 指的是请求头;

Body 指的是正文,可以在里面添加多种格式的正文,例如 json,x-www-form-urlencoded等;

2. 调用SocketAPI

http 协议是一个文本协议,只需要按照 http 协议的格式拼接字符串即可,如下:

java 复制代码
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class HttpClient {
    private Socket socket;
    private String serverIp;
    private int port;

    public HttpClient(String serverIp, int port) throws IOException {
        socket = new Socket(serverIp, port);
        this.serverIp = serverIp;
        this.port = port;
    }

    public String get(String url){
        // 按照 http 协议构造 http 请求报文
        StringBuilder request = new StringBuilder();
        // 首行
        request.append("GET " + url + " HTTP/1.1\n");
        // 请求头
        request.append("Host: " + serverIp + ":" + port + "\n");
        // 空行
        request.append("\n");

        String response = null;
        try(OutputStream outputStream = socket.getOutputStream();
            InputStream inputStream = socket.getInputStream()){
            // 发送 http 请求
            outputStream.write(request.toString().getBytes());
            // 接收 http 响应
            byte[] buffer = new byte[1024 * 1024];
            int n = inputStream.read(buffer);
            response = new String( buffer, 0, n, "utf-8");

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return response;
    }

    public String post(String url, String body){
        // 按照 http 协议构造 http 请求报文
        StringBuilder request = new StringBuilder();
        // 首行
        request.append("POST " + url + " HTTP/1.1\n");
        // 请求头
        request.append("Host: " + serverIp + ":" + port + "\n");
        request.append("Content-Length: " + body.getBytes().length + "\n");
        request.append("Content-Type: txt/plain\n");
        // 空行
        request.append("\n");
        // 正文
        request.append(body);

        String response = null;
        try(OutputStream outputStream = socket.getOutputStream();
            InputStream inputStream = socket.getInputStream()){
            outputStream.write(request.toString().getBytes());
            // 接收 http 响应
            byte[] buffer = new byte[1024 * 1024];
            int n = inputStream.read(buffer);
            response = new String(buffer, 0, n, "utf-8");

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return response;
    }

    public static void main(String[] args) throws IOException {
        HttpClient httpClient = new HttpClient("www.sogou.com", 80);
        String getResp = httpClient.get("/index.html");
        System.out.println(getResp);
    }
}

实际应用中,基本不需要自己手动构造 http 协议请求,而是使用一些第三方库;

第三方库的代码,可以在 Postman 中把请求构造好,点击 </> 图标,查看 Postman 给出的实现;

3. html 和 js

实际工作中,会涉及到用 html 和 js 构造 http 请求;

四、HTTPS

1. 基本概念

HTTPS 是在 HTTP 的基础上引入了一个 SSL 加密层;

引入 HTTPS 的主要目的是防止数据被劫持篡改;

解决安全问题的核心就是加密,加密和破解是一个对抗的过程,理论上没有绝对的安全,只要破解的成本高于数据本身的价值,就是绝对安全的;

明文:加密前的数据;

密文:加密后的数据;

密钥:加密和解密过程中,需要用到密钥;

**对称加密:**加密和解密用的是同一个密钥;

非对称加密:

加密和解密用的是两个不同的密钥,两个不同的密钥一个是公钥,一个是私钥,公钥和私钥是成对出现的;

使用公钥加密,就需要使用私钥解密;

使用私钥加密,就需要使用公钥解密;

公钥是公开的,私钥是自己保存好的;

对 HTTPS 数据进行解密,得到的就是 HTTP 格式的数据;

引入加密是为了对传输的数据进行保护,加密的主要对象就是 HTTP 协议的请求/响应头和正文;

2. 对称加密

对称加密,加密和解密使用的是同一个密钥;

不同的客户端需要使用不同的密钥;

客户端连接服务器时,需要生成一个随机的密钥,传输给服务器,也可以服务器生成密钥传输给客户端,关键在于要将密钥传输给对方;

传输时,如果经过黑客的设备,传输的密钥就会被截获,加密就形同虚设;

3. 非对称加密

引入非对称加密的主要目的是对对称密钥进行加密,确保对称密钥的安全性;

非对称加密的加密解密成本远高于对称加密,直接使用非对称加密,如果数据量较大,加密和解密的开销就会非常大,因此非对称加密不适用于数据量较大的场景;

非对称加密使用一对密钥,一个公钥,一个私钥,公钥加密使用私钥解密,私钥加密使用公钥解密;

服务器持有私钥,并将公钥发送给客户端,黑客设备也能获取到公钥;

客户端可服务器交互时,假设数据经过黑客的设备:

  1. 客户端使用公钥加密,将对称密钥发送给服务器;
  2. 黑客设备截获到这个数据,但是没有私钥,不能解密,无法获取对称密钥;
  3. 对称密钥转发给服务器后,服务器使用私钥解密,获取对称密钥;
  4. 后续双方使用对称密钥,加密数据,进行通信;由于黑客设备没有获取到对称密钥,后续的通信就是安全的;

交换密钥的过程就是 SSL 的握手过程;

4. 中间人攻击

假设客户端生成的堆成密钥是 key;

非加密过程中服务器使用的公钥和私钥分别是 pub1 和 pri1;

针对非对称密钥加密的过程,黑客设备也可以生一对公钥和私钥 pub2 和 pri2;

过程如下:

  1. 客户端请求服务器的公钥时,服务器返回 pub1;
  2. 黑客设备将 pub1 替换为 pub2,返回给客户端;
  3. 客户端拿到 pub2 后,使用 pub2 针对 key 进行加密,并将加密后的密钥发送给服务器;
  4. 黑客设备拿到使用 pub2 加密的 key 后,使用 pri2 进行解密,获取到 key;
  5. 黑客设备再使用 pub1 对 key 进行加密,将加密后的 key 发送给服务器;
  6. 服务器拿到加密的 key 后,使用 pri1 进行解密,拿到对称密钥 key;
  7. 后续客户端和服务器使用对称密钥进行通信,由于黑客设备也获取到了对称密钥 key,因此后续的通信都将被黑客截获;

5. 公证机构

上述中间人攻击的过程,关键在于客户端无法区分拿到的公钥是服务器的还是黑客设备的;

如果客户端能识别服务器的公钥,上述问题将迎刃而解;

于是为了解决上述问题,引入了第三方公证机构;

搭建服务器的人,向第三方公证机构申请,公证机构为服务器提供一个证书;

证书的内容:

证书是一个结构化的数据,包含多个属性,有服务器的域名,证书的有效时间,服务器的公钥,公证机构的信息,以及证书的签名等;

颁发证书的公证机构,会在办法证书的时候给这个证书计算一个校验和,然后用公证机构的私钥给这个校验和加密,就得到了证书的签名;

签名本质上是一个经过加密的校验和;

证书中的其它字段,通过一系列的算法,如 MD5,CRC等,得到一个较短的字符串,表示校验和;

证书的验证过程:

每次通讯的之前,客户端先发送信息,向服务器申请证书;

客户端拿到证书后,针对证书进行验证:

  1. 按照相同的校验和算法,保证书的其他字段都重新算一遍,得到校验和 1;

  2. 使用系统的内置的公证机构的公钥对数字签名进行解密,得到校验和 2;

  3. 对比两个校验和,如果没发生变化,则表示证书没有被篡改,里面的公钥就是服务器的公钥;

黑客设备能否篡改服务器公钥?

不能,因为一旦篡改公钥,客户端在计算证书的校验和的时候就会和证书自带的校验和不同;

黑客设备能否篡改证书自带的数字签名?

不能,黑客设备可以通过第三方公证机构的公钥进行解密,但是不能篡改:

  • 如果篡改了,没有第三方公证机构的私钥,无法进行加密;
  • 如果使用黑客设备的私钥进行加密,则客户端无法通过第三方公证机构的公钥解密;

黑客能否自己去第三方机构申请证书?

可以申请证书,但是不能替换服务器的,因为域名不一样,域名都是唯一的;即使替换了证书,也很容易被客户端发现;


相关推荐
盟接之桥3 小时前
盟接之桥EDI软件:中国制造全球化进程中的连接挑战与路径探索
大数据·网络·人工智能·安全·制造
ZeroNews内网穿透5 小时前
什么是TCP/UDP/HTTP?它们如何影响你的内网穿透体验?
tcp/ip·http·udp
2024暴富6 小时前
Http升级Https使用Certbot申请证书并免费续期
http·阿里云·https·ssl
程序猿(雷霆之王)6 小时前
传输层协议——UDP/TCP
网络·tcp/ip·udp
蒋星熠7 小时前
网络协议深度解析:从OSI七层模型到现代互联网通信的技术实战
网络·后端·python·网络协议·http·性能优化·tcp
时空潮汐7 小时前
个人用户无公网 IP 访问群晖 NAS:神卓 N600 的安全便捷方案(附踩坑经验)
网络协议·安全·群晖·nas·威联通·绿联·极空间
钱工聊运维7 小时前
从“连不上网”到“玩转路由”:路由器配置与静态路由实战(小白也能轻松掌握)
网络·网络工程师·软考·ipv6·静态路由
GCKJ_08249 小时前
【观成科技】活跃黑产团伙“黑猫”攻击武器加密通信分析
网络·科技·信息与通信
不努力谁会可怜你?9 小时前
HTTPS报文在SSL/TLS证书安全隧道传输的原理
网络协议·https·stl·ssl·tls