HTTP:超文本传输协议。是一种应用非常广泛的应该层协议。
所谓 “超文本” 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些其他的资源, 比如图片,视频, 音频等二进制的数据。
完整应用是由前端+后端构成的,而前、后端之间的通讯是要依靠 HTTP来完成的。这就像消费者在网上买东西一样,商家和买件之间,需要一个快递公司,而 HTTP 就是这个快递公司,其中的请求方法GET/POST 相当于不同类型的快递类型(标准快递、加急快递)。
当我们在浏览器中输入一个 “网址”, 此时浏览器就会给对应的服务器发送一个 HTTP 请求(request)。对方服务器收到这个请求之后, 经过计算处理, 就会返回一个 HTTP 响应(response)。
通过 F12 打开 chrome 的开发者工具, 切换到 Network 标签页。 然后刷新页面即可看到如下图效果。每一条记录都是一次 HTTP 请求/响应。
HTTP 是一个文本格式的协议. 可以通过 Chrome 开发者工具或者 Fiddler 抓包, 分析 HTTP 请求/响应的细节.
左侧窗口显示了所有的 HTTP请求/响应, 可以选中某个请求查看详情.
右侧上方显示了 HTTP 请求的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
右侧下方显示了 HTTP 响应的报文内容. (切换到 Raw 标签页可以看到详细的数据格式)
GET方法:GET 是最常用的 HTTP 方法. 常用于获取服务器上的某个资源。在浏览器中直接输入 URL, 此时浏览器就会发送出一个 GET 请求.
POST方法:POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面)。
GET和POST的区别:
①GET 请求的数据是通过 URL 传递的,即将数据拼接到 URL 的后面,以 ? 分隔,参数之间以 &符号分隔。因此, GET 请求对于传输的数据大小是有限制的,通常在几千个字符之内。而 POST 请求则是将数据放在 HTTP请求的请求体中进行传输,没有大小限制,可传输较大的数据量。
②GET 请求传输的数据是明文的,因此数据容易被拦截和篡改。而 POST请求传输的数据放在请求体中,所以相对隐私一些。
③GET 请求是可以被缓存的,当浏览器再次请求同一个 URL时,可以从缓存中直接获取数据,加快访问速度。而 POST 请求是不可缓存的,因为每次提交数据都可能导致服务器状态的改变。
④GET请求的数据会被浏览器保存在历史记录和服务器日志中,容易被恶意程序利用。而 POST 请求不会被保存在历史记录和服务器日志中,相对更加安全。
平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符). 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
http : 协议方案名. 常见的有 http 和 https, 也有其他的类型. (例如访问 mysql 时用的jdbc:mysql )。
user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略。
www.example.jp:服务器地址. 此处是一个 “域名”, 域名会通过 DNS 系统解析成一个具体的 IP 地址(通过 ping 命令可以看到IP地址)。
80:端口号。 当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口.
dir/index.htm:带层次的文件路径。
?:参数的开始符号
uid=1:查询字符串(query string). 本质是一个键值对结构. 键值对之间使用 & 分隔. 键和值之间使用 = 分隔。这部分也被称为query string , 其中的 key 和 value 的取值和个数 完全都是程序猿自己约定的. 通过这样的方式来自定制传输我们需要的信息给服务器。
ch1:片段标识符,主要用于页面的跳转,快速定位标签。
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现。比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.
HTTP的版本号用的比较广泛的是HTTP1.1。
key-value的键值对。每个键值对占一行. 键和值之间使用分号分割。
常见的报头:
Host:表示服务器主机的地址和端口.
Content-Length:表示 body 中的数据长度.
Content-Type:表示请求的 body 中的数据格式.
application/x-www-form-urlencoded: form 表单提交的数据格式。
application/json: 数据为 json 格式
User-Agent (UA):表示浏览器/操作系统的属性
Referer:表示这个页面是从哪个页面跳转过来的
Cookie :Cookie是一种客户端保存数据的机制,典型的应用场景是保存用户的登录信息。
删除了本地的cookie之后,再访问网站时会判断为未登录状态。
Session:识别是哪一个用户访问了服务器。
session工作在服务器端,服务器创建一个session对象,这个session对象可以用来保存当前会话相关的数据。服务器维护着一个Map用来保存session,并生成一个sessionld做为Key,session做为value。
每一个session本身也是一个Map,可以自定义Key与value。服务器通过响应头中的set-cookie把sessionld返回给客户端,客户端每次请求时把sessionld发送到服务器,服务器就可以区分是哪个客户端发来的请求,并从服务器维护的Map获取到针对当前会话保存的数据。
工作流程: 当用户登陆的时候,服务器在 Session 中新增一个新记录,并把sessionld/token 返回给客户端(例如通过HTTP 响应中的 Set-Cookie 字段返回)。客户端后续再给服务器发送请求的时候,需要在请求中带上sessionld/ token。(例如过 HTTP 请求中的 Cookie字段带上)服务器收到请求之后,根据请求中的 sessionld/token在Session信息中获取到对应的用户信息再进行后续操作。
程序员传参相关的。
表示一个页面的访问结果是成功还是失败还是其他情况。
200: 这是一个最常见的状态码, 表示访问成功。
404 Not Found:没有找到资源。浏览器输入一个 URL, 目的就是为了访问对方服务器上的一个资源. 如果这个 URL 标识的资源不存在, 那么就会出现 404。
403 Forbidden:表示访问被拒绝. 有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆直接访问, 就容易见到 403。
500 Internal Server Error:服务器出现内部错误.一般是服务器的代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码。
504 Gateway Timeout:当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况。
302 Move temporarily:临时重定向.临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI。
301 Moved Permanently:永久重定向. 当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址. 301 也是通过 Location 字段来表示要重定向到的新地址。
响应报头的基本格式和请求报头的格式基本一致. 类似于 Content-Type , Content-Length 等属性的含义也和请求中的含义一致。
响应中的 Content-Type 常见取值有以下几种:
1.text/html : body 数据格式是 HTML
2.text/css : body 数据格式是 CSS
3.application/javascript : body 数据格式是 JavaScript
4.application/json : body 数据格式是 JSON
HTTP 协议内容都是按照文本的方式明文传输的. 这就导致在传输过程中出现一些被篡改的情况。HTTPS 也是一个应用层协议. 是在 HTTP 协议的基础上引入了一个加密层。
客户端使用 HTTPS 访问服务器端。
服务器端返回数字证书,以及使用非对称加密,生成一个公钥给客户端(私钥服务器端自己保留)。
客户端验证数字证书是否有效,如果无效,终止访问,如果有效:
①使用对称加密生成一个共享秘钥;
②使用对称加密的共享秘钥加密数据;
③使用非对称加密的公钥加密(对称加密生成的)共享秘钥;
④发送加密后的秘钥和数据给服务器端。
服务器端使用私钥解密出客户端(使用对称加密生成的)共享秘钥,再使用共享秘钥解密出数据的具体内容。之后客户端和服务器端就使用共享秘钥加密的内容进行交互了。
由于对称加密的效率比非对称加密高很多, 因此只是在开始阶段协商密钥的时候使用非对称加密, 后续的传输仍然使用对称加密。
加密就是把 明文 (要传输的信息)进行一系列变换, 生成 密文 。网络传输中不再直接传输明文了, 而是加密之后的 “密文”。
解密就是把 密文 再进行一系列变换, 还原成 明文 。
在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为 密钥 。
加密的方式有很多, 但是整体可以分成两大类: 对称加密 和 非对称加密。
对称加密其实就是通过同一个 “密钥” , 把明文加密成密文, 并且也能把密文解密成明文。发送方和接收方必须共享密钥才能进行通信,这使得对称加密算法在保密性和性能方面非常高效。
但是服务器同一时刻其实是给很多客户端提供服务的。这么多客户端, 每个人用的秘钥都必须是不同的(如果是相同那密钥就太容易扩散了, 黑客就也能拿到了)。因此服务器就需要维护每个客户****端和每个密钥之间的关联关系, 这也是个很麻烦的事情。比较理想的做法, 就是能在客户端和服务器建立连接的时候, 双方协商确定这次的密钥是啥。但是如果直接把密钥明文传输, 那么黑客也就能获得密钥了~~ 此时后续的加密操作就形同虚设了。因此密钥的传输也必须加密传输! 但是要想对密钥进行对称加密, 就仍然需要先协商确定一个 “密钥的密钥”. 这就成了 “先有鸡还是先有蛋” 的问题了,此时密钥的传输再用对称加密就行不通了,就需要引入非对称加密.
非对称加密要用到两个密钥, 一个叫做 “公钥”, 一个叫做 “私钥”. 发送方使用接收方的公钥进行加密,而接收方使用其私钥进行解密。公钥和私钥是配对的. 最大的缺点就是运算速度非常慢,比对称加密要慢很多。
那么接下来问题又来了:客户端如何获取到公钥?客户端如何确定这个公钥不是黑客伪造的?
在客户端和服务器刚一建立连接的时候, 服务器给客户端返回一个 证书。这个证书包含了刚才的公钥, 也包含了网站的身份信息。
这个证书就好比人的身份证, 作为这个网站的身份标识. 搭建一个 HTTPS 网站要在CA机构先申请一个证书. (类似于去公安局办个身份证)。