HTTP的影子
作用:平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符). 互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.
协议方案名
:常见的有 http 和 https, 也有其他的类型,换句话说,URL不仅仅针对HTTP协议设计的,网络中是所有资源都可以用URL来命名
登录信息名
:指定用户名和密码作为从服务器端获取资源时毕业的登录信息,这项是可选的
服务器地地址
:www.exanple.jp此处是一个 “域名”, 域名会通过 DNS 系统解析成一个具体的 IP 地址.(通过 ping 命令可以看到)
端口号
: 指定服务器连接的网络端口号,此项也是可选项,如果省略,则使用默认端口号
带层次的文件路径
因为即便是同一个进程,也会管理着多个资源,所以我们指定服务器上的文件路径来定位特指的资源
查询字符串(query string)
针对已指定的文件路径的资源,可以使用查询字符串传入任意的参数
片段标识
此 URL 中省略了片段标识. 片段标识主要用于页面内跳转.
什么是URI
URI(统一资源标识符)就类似一个独一无二的身份标识。准确的说是某个网络资源的特有标识(用来区别于其他资源的独一无二的标识)有这样一个需求:
要求找到一本书(书就是资源),这本书在A省份/B市/C区/D街道/xx栋/392-1住户/1号房间/名字叫做《xxx》 (这里就是模拟我们输入网址进行HTTP请求)
- 那么此时的 《xxx》 这本书 对于 1号房间 来说就是URI
- 此时的D街道/xx栋/392-1住户/1号房间/名字叫做《xxx》这本书 对于 A省份/B市/C区 来说就是URI
- 可以看出URI是不固定的,是相对来说的,具体是什么就看你的参照角度是什么。(不同请求参照角度不一样,所以他们的返回uri有差异)
- 由此总结:URI是一个标识,用来区别于其他资源的标识。
什么是URL
那么再来说一说什么是URL(统一资源定位符)。URL就是每次我们输入网址访问某个网站时,浏览器上输入的那一行内容。比如:http://baidu.com
这是一个URL
- 类比上面的例子,我们的A省份/B市/C区/D街道/xx栋/392-1住户/1号房间/名字叫做《xxx》就是一个URL,类似一个绝对地址,根据这个地址肯定能找到这本书
- 但是只根据URI,我们是找不到这本书的,必须有前提条件
- 我们的URL包含了协议,ip地址,端口号,和资源的在服务器下的相对路径,类似绝对路径,也就肯定能找到这个数据
URI和URL的关系
URI是URL的父级,URL是URI的子级。
明明是URL包含了URI为啥URI反而是父级
- 请注意,我这里用的是级别来描述,而不是包含。
- 我没有说URL是URI的一部分,而是说是他的子级。
- 想要理解这个概念,最好的说明就是Java的继承关系。URL继承了URI。这样来看是不是瞬间就明白了。
- 因为URL继承了所有URI的内容,所以它比URI更加详细,但是URI是它的父级。
有什么作用
URL的作用
- URL一般是一个完整的链接,我们可以直接通过这个链接(url)访问到一个网站,或者把这个url复制到浏览器访问网站。
URI的作用
- URI并不是一个直接访问的链接,而是相对地址(当然如果相对于浏览器那么uri等同于url了)。这种概念更多的是用于编程中,因为我们没必要每次编程都用绝对url来获取一些页面,这样还需要进行分割“http://xx/xxx”前面那一串,所以编程的时候直接request.getRequestURI就行了,当然如果是重定向的话,就用URL。
URL中的可省略部分
协议名: 可以省略, 省略后默认为 http://
ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性).
端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自动设为 443.
带层次的文件路径: 可以省略. 省略后相当于访问 /
查询字符串: 可以省略
片段标识: 可以省略
情景一
情景二通过资源来引用另一个资源
URL编码的大体规则
一次完整的HTTP分为
所以对应着两种格式:请求报文格式,响应报文格式
从需求分析应该有哪些内容
报文主体和实体主体的差异
例子
当涉及到编码时,此时我们的实体主体应该是
This is the data in the first chunk and this is the second one consequence
而报文主体则为
25 This is the data in the first chunk 1C and this is the second one 3 con 8 sequence
那么此时,报文主体和此时的实体主体就变得不一致了。
例子
例子
为什么 HTTP 报文中要存在 “空行”?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-59PNlaad-1681456831779)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
如何写一个HTTP客户端
自己写的HTTP请求——模拟HTTP客户端
package com.lsc.demo;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class MyHttpClient {
public static void main(String[] args) throws Exception {
// 只能进行一次请求-响应的 HTTP 客户端
// 主机 127.0.0.1
// 端口(进程) 8080
// 资源路径 /hello.html
try (Socket socket = new Socket("127.0.0.1", 8080)) {
// 准备 HTTP 请求内容
// 文本 String
// 格式:请求行
String requestLine = "GET /hello.html HTTP/1.0\r\n";
// 请求头:完全可以没有,但必须一个空行结尾
String requestHeader1 = "Name: LSC\r\n\r\n"; // 请求头中共有 1对 key-value
String requestHeader2 = "Name: LSC\r\nAge: 1993\r\n\r\n"; // 请求头中共有 2对 key-value
String requestHeader3 = "\r\n"; // 请求头中共有 0 对 key-value
// 请求体,GET 是没有请求体
// 最终的请求 —— 要发送给服务器的东西
String request = requestLine + requestHeader3;
// 发送服务器的过程
byte[] requestBytes = request.getBytes("ISO-8859-1"); // 字符集编码
// 发送(数据会经由 TCP、IP、以太网发送给服务器)
OutputStream os = socket.getOutputStream();
os.write(requestBytes);
os.flush();
// 请求既然已经发送,我们要做的就是等待响应
InputStream is = socket.getInputStream();
Scanner scanner = new Scanner(is, "UTF-8"); // 响应的前面字符集应该是 ISO-8859-1,后边是 UTF-8
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
}
}
}
自己模拟的HTTP服务器
package com.lsc.demo;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class MyHttpServer {
public static void main(String[] args) throws IOException {
try (ServerSocket serverSocket=new ServerSocket(8080)){
while (true){
Socket socket=serverSocket.accept();//三次握手建立结束
// 读取用户的请求 这里就不具体读了,一律采用相同的方式回应
//发送响应 响应体 资源内容
// Content-Type: 浏览器应该按照什么格式来看到我们响应的资源内容的(资源内容放在响应体中)
//响应体的资源
String responseBody="Welcome MyHttpServer
";
byte[] responseBodyBytes=responseBody.getBytes(StandardCharsets.UTF_8);
int contentLength=responseBody.length();
String response="HTTP/1.0 200 OK \r\n"
+"Sever: lsc\r\n"
+"ContentType: text/html; charset=utf-8\r\n"
+"ContentLength:"+contentLength+"\r\n"
+"\r\n";
byte[] responseBytes=response.getBytes("ISO-8859-1");
OutputStream os=socket.getOutputStream();
os.write(responseBytes);
os.write(responseBodyBytes);
os.flush();
//发送完毕之后,直接关闭TCP连接
socket.close();
}
}
}
}
我们自己写的服务器的信息
什么方式能够激发GET方法
POST,不借助第三方的工具的情况下,只有两种方法可以做到
img标签的自动请求
a标签的点击之后请求
表单
,from表单的提交浏览器会使用post方法,如果默认不写,就是GET使用JavaScripts来发起请求 (ajax)
//1实例化一个XMLHttpRequest对象
var xhr=new XMLHttpRequest()
//2调用对象的open方法, 设置发送请求的方法 资源路径
//xhr.open('get','/demo')
xhr.open('post,'/demo')
//设置回调函数,当/demo资源响应返回的时候,应该干什么
//提供事件绑定机制
//事件:load事件(当响应返回的时候)
//事件处理 回调函数
xhr.onload=function(){
console.log(xhr.status)//打印响应的状态 成功是200
console.log(xhr.responseText)//打印响应的响应体
//还有其他东西,现在不关心
}
//4真正的发送请求出去
xhr.send()
执行顺序
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0QfdCRXG-1681456831784)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\0613d54e02d24764809af7a55f517522.png)]
关于form表单发起POST
DELETE 方法用来删除文件, 是与 PUT 相反的方法。
DELETE 方法按请求 URI 删除指定的资源。
HTTP/1.1 的 DELETE 方法本身和 PUT 方法一样不带验证机制, 所以一般的 Web 网站也不使用 DELETE 方法。 当配合 Web 应用程序的验证机制, 或遵守 REST 标准时还是有可能会开放使用的。
TRACE 方法是让 Web 服务器端将之前的请求通信环回给客户端的方法。
对比成sql语句去理解
这种理解方式其实也就是我们俗称的RESTful的理解形式
REST:Representational State Transfer,表现层资源状态转移
- RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用 XML 格式定义或 JSON 格式定义。最常用的数据格式是JSON。由于JSON能直接被JavaScript读取,所以,使用JSON格式的REST风格的API具有简单、易读、易用的特点。
- REST 是面向资源的,每个资源都有一个唯一的资源定位符(URI)。每个URI代表一种资源(resource),所以URI中不能有动词,只能有名词,而且所用的名词往往与数据库的表名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以URI中的名词也应该使用复数。
RESTful的实现
具体说,就是 HTTP 协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET 用来获取资源,POST 用来新建资源,PUT 用来更新资源,DELETE用来删除资源。
REST 风格提倡 URL 地址使用统一的风格设计,从前到后各个单词使用斜杠分开,不使用问号键值对方式携带请求参数,而是将要发送给服务器的数据作为 URL 地址的一部分,以保证整体风格的一致性。
操作 传统方式 REST风格
查询操作 getUserById?id=1 user/1–>get请求方式
保存操作 saveUser user–>post请求方式
删除操作 deleteUser?id=1 user/1–>delete请求方式
更新操作 updateUser user–>put请求方式
没有RESTful之前的用法
http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据
http://127.0.0.1/user/save POST 新增用户
http://127.0.0.1/user/update POST 修改用户信息
http://127.0.0.1/user/delete/1 GET/POST 删除用户信息RESTful用法:
http://127.0.0.1/user/1 GET 根据用户id查询用户数据
http://127.0.0.1/user POST 新增用户
http://127.0.0.1/user PUT 修改用户信息
http://127.0.0.1/user/1 DELETE 删除用户信息
- 之前的操作有什么问题呢?你每次请求的接口或者地址,都在做描述,例如查询的时候用了query,新增的时候用了save,其实完全没有这个必要,我使用了get请求,就是查询.使用post请求,就是新增的请求,我的意图很明显,完全没有必要做描述,这就是为什么有了restful.
客户端使用 HTTP 协议访问服务器时, 会经常采用类似 www.hackr.jp这样的主机名和域名。
在相同的 IP 地址下, 由于虚拟主机可以寄存多个不同主机名和域名的 Web 网站, 因此在发送 HTTP 请求时, 必须在 Host 首部内完整指定主机名或域名的 URI。
HTTP 通信时, 除客户端和服务器以外, 还有一些用于通信数据转发的应用程序, 例如代理、 网关和隧道。 它们可以配合服务器工作。
这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器, 并且能接收从那台服务器发送的响应再转发给客户端。
代理有多种使用方法, 按两种基准分类。 一种是是否使用缓存, 另一种是是否会修改报文。
缓存代理
透明代理
为什么使用代理
使用代理服务器的理由有: 利用缓存技术减少网络带宽的流量, 组织内部针对特定网站的访问控制, 以获取访问日志为主要目的, 等等。
网关是转发其他服务器通信数据的服务器, 接收从客户端发送来的请求时, 它就像自己拥有资源的源服务器一样对请求进行处理。 有时客户端可能都不会察觉, 自己的通信目标是一个网关。
网关能使通信线路上的服务器提供非 HTTP 协议服务。利用网关能提高通信的安全性, 因为可以在客户端与网关之间的通信线路上加密以确保连接的安全。 比如, 网关可以连接数据库, 使用SQL语句查询数据。 另外, 在 Web 购物网站上进行信用卡结算时,网关可以和信用卡结算系统联动。
隧道可按要求建立起一条与其他服务器的通信线路, 届时使用 SSL等加密手段进行通信。 隧道的目的是确保客户端能与服务器进行安全的通信。
隧道本身不会去解析 HTTP 请求。 也就是说, 请求保持原样中转给之后的服务器。 隧道会在通信双方断开连接时结束。
隧道是在相隔甚远的客户端和服务器两者之间进行中转, 并保持双方通信连接的应用程序。
缓存服务器的优势在于利用缓存可避免多次从源服务器转发资源。 因此客户端可就近从缓存服务器上获取资源, 而源服务器也不必多次处理相同的请求了。
仅记录在 RFC2616 上的 HTTP 状态码就达 40 种, 若再加上WebDAV(Web-based Distributed Authoring and Versioning, 基于万维网
的分布式创作和版本控制) (RFC4918、 5842) 和附加 HTTP 状态码(RFC6585) 等扩展, 数量就达 60 余种。 别看种类繁多, 实际上经
常使用的大概只有 14 种。 接下来, 我们就介绍一下这些具有代表性的 14 个状态码。
表示从客户端发来的请求在服务器端被正常处理了。在响应报文内, 随状态码一起返回的信息会因方法的不同而发生改变。 比如, 使用 GET 方法时, 对应请求资源的实体会作为响应返回; 而使用 HEAD 方法时, 对应请求资源的实体首部不随报文主体作为响应返回(即在响应中只返回首部, 不会返回实体的主体部分) 。
如何做到200
访问正确的资源路径
使用正确的方法
参数必须符合
比如
比喻
站内和站外重定向
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tWFRFdlE-1681456831800)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\0f5bae79bf1a4021bbe3380639c56a22.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YHM9f82i-1681456831800)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
永久重定向和临时重定向
临时重定向的继续划分
我们知道重定向是两次请求响应
改状态码标识客户端发送附带条件的请求,服务器段允许请求访问资源,但因为请求为满足条件的情况后,直接返回304 Not Modified(服务器端资源为改变,可直接使用客户端为未期的缓存)。304状态返回后,不包含任何响应的主体部分
304状态码: 客户端有缓存情况下服务端的一种响应。自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。
1 附带条件的请求是指采用 GET方法的请求报文中包含 If-Match, If-ModifiedSince, If-None-Match, If-Range, If-Unmodified-Since 中任一首部。
如何做到304
如何做到400
@RequestMapping(
value = {"test1","test2"},
method = {RequestMethod.GET,RequestMethod.POST},
params = {"username","password!=123","!gender","age=22"}
)
public String test(){
return "test";
}
如何做到403
该状态码表明服务器上无法找到请求的资源。 除此之外, 也可以在服务器端拒绝请求且不想说明理由时使用。
如何做到404
该状态码表明服务器端在执行请求时发生了错误。 也有可能是 Web应用存在的 bug 或某些临时的故障。
如何做到500
状态码和状况的不一致不少返回的状态码响应都是错误的, 但是用户可能察觉不到这点。比如 Web 应用程序内部发生错误, 状态码依然返回 200 OK, 这种情况也经常遇到。
content-type(内容类型)
大文本类型
应用类型
多媒体
from表单文件上传
主要和
配合JSON格式
具体了解看博客——http://t.csdn.cn/8sJrb
返回类对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qVCPqjuB-1681456831806)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
动态资源
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EyNX0b5G-1681456831809)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-puibeRuD-1681456831810)(data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==)]编辑
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TrCmRZ1q-1681456831810)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\9f71ce2743f24ec081ec16760ec02e8c.png)]
总之,文件上传的时候(通过from表单上传),必须指定enctype为multipart/form-date.这样请求体中不仅仅携带要上传的文件名,还包含文件的内容信息
前提:一开始设计的HTTP协议,本身是无状态的协议
HTTP 是一种不保存状态, 即无状态(stateless) 协议。 HTTP 协议自身不对请求和响应之间的通信状态进行保存。 也就是说在 HTTP 这个级别, 协议对于发送过的请求或响应都不做持久化处理
不可否认, 无状态协议当然也有它的优点。 由于不必保存状态, 自然可减少服务器的 CPU 及内存资源的消耗。 从另一侧面来说, 也正是因为 HTTP 协议本身是非常简单的, 所以才会被应用在各种场景里。
客户端第一次发送请求给服务器
同一个客户端第二次发信息给服务器
name=value
,但是服务器可以一次设置多个 cookie,所以有时候说 cookie 是「一组」键值对儿,这也可以说得通。在服务器颁发Cookie
响应头返回了设置的相应的cookie信息
在浏览器找到对应Cookie的存储位置
下次请求携带Cookie
要利用Cookie做到HTTP协议有状态(跨请求-响应有逻辑关系)
对于服务器,需要有设置凭证的职责,在HTTP中的表现为HTTP响应中,添加Set-Cookie响应头,value是要设置的cookie信息
对于客户端,有保存凭证的职责,在HTTP的具体表现为,客户端需要理解Set-Cookie这个响应头的职责,根据响应中的Set-Cookie的value,将Cookie的信息解析并保存
对于客户端,在发送任意请求时,都有携带属于本网站的所有的Cookie的职责
经过这一套cookie的流程,我们就可以实现http的有状态,能让我们的服务器能够认识我们的客户
Session:是保存在服务器的,专属某次会话的,一组数据,可以跨请求访问到(生命周期是跨请求的),通常Session中保存的数据也可以视为name-value.,一般cookie设置session-id.这样客户端和服务器之间仍然使用cookie机制,只是cookie只传递SessionId即可(cookie还是放在我们的请求头和响应头中的,存储的是session-id),大头数据全部保存在服务器
HttpServletRequest类下,有一个HttpSession getSession(boolean create)来获取session
HttpSession对象就是用来获得相应的session的信息,是通过 getSession函数获得,根据请求头的cookie信息来获得
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0GsJfNdy-1681456831816)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\3b8e85ead117493bb17b6e84a823241d.png)]
private final Map<String,Map<String,Object>> 模拟session的结构=new HashMap<>();
到现在为止, 我们已了解到 HTTP 具有相当优秀和方便的一面, 然而HTTP 并非只有好的一面, 事物皆具两面性, 它也是有不足之处的。HTTP 主要有这些不足, 例举如下。
HTTPS 并非是应用层的一种新协议。 只是 HTTP 通信接口部分用SSL(Secure Socket Layer) 和 TLS(Transport Layer Security) 协议代替而已。通常, HTTP 直接和 TCP 通信。 当使用 SSL时, 则演变成先和 SSL通信, 再由 SSL和 TCP 通信了。 简言之, 所谓 HTTPS, 其实就是身披SSL协议这层外壳的 HTTP。
在采用 SSL后, HTTP 就拥有了 HTTPS 的加密、 证书和完整性保护这些功能
TCP/IP 是可能被窃听的网络
如果要问为什么通信时不加密是一个缺点, 这是因为, 按TCP/IP 协议族的工作机制, 通信内容在所有的通信线路上都有可能遭到窥视。所谓互联网, 是由能连通到全世界的网络组成的。 无论世界哪个角落的服务器在和客户端通信时, 在此通信线路上的某些网络设备、 光缆、 计算机等都不可能是个人的私有物, 所以不排除某个环节中会遭到恶意窥视行为。
即使已经过加密处理的通信, 也会被窥视到通信内容, 这点和未加密的通信是相同的。 只是说如果通信经过加密, 就有可能让人无法破解报文信息的含义, 但加密处理后的报文信息本身还是会被看到的。比如之前臭名昭著的运营商劫持
在目前大家正在研究的如何防止窃听保护信息的几种对策中, 最为普及的就是加密技术。 加密的对象可以有这么几个。
还有一种将参与通信的内容本身加密的方式。 由于 HTTP 协议中没有加密机制, 那么就对 HTTP 协议传输的内容本身加密。 即把HTTP 报文里所含的内容进行加密处理。在这种情况下, 客户端需要对 HTTP 报文进行加密处理后再发送请求。诚然, 为了做到有效的内容加密, 前提是要求客户端和服务器同时具备加密和解密机制。 主要应用在 Web 服务中。 有一点必须引起注意, 由于该方式不同于 SSL或 TLS 将整个通信线路加密处理, 所以内容仍有被篡改的风险。
前提了解相关加密算法
我们可以利用对称加密算法来实现明文到密文的转换,来进行传输,但是如何传输对称算法的密钥却是一种问题
以共享密钥方式加密时必须将密钥也发给对方。 可究竟怎样才能安全地转交? 在互联网上转发密钥时, 如果通信被监听那么密钥就可会落入攻击者之手, 同时也就失去了加密的意义。 另外还得设法安全地保管接收到的密钥。
解决通信使用明文( 不加密) , 内容可能会被窃听的问题
首先服务器要准备好非对称算法公钥和私钥(私钥不能泄露)
首先我们的客户端去申请回来服务器的公钥(明文传输),因为这个公钥是用来将数据加密的,不能解密,所以别人知道了也无所谓
客户端生成一段随机数,来作为对称算法的密钥,然后通过非对称算法公钥来加密(只有服务器的私钥才能解密),所以其他人是不知道这个对称密钥的明文的,发送给服务器
服务接收到这段密文,然后通过非对称算法的私钥来获得对称算法的密钥(完成了对称算法的密钥的安全传输)
得到这个对称算法的密钥,服务器和客户端就可以通过对称算法来完成数据的加密传输
为啥要用对称算法传输数据,而不直接用非对称算法呢?
因为公开密钥加密处理起来比对称算法的共享密钥更复杂,若在通信时使用非对称算法,效率会很低
但是这套流程还是存在着漏洞
不验证通信方的身份就可能遭遇伪装,HTTP 协议中的请求和响应不会对通信方进行确认。 也就是说存在“服务器是否就是发送请求中 URI 真正指定的主机, 返回的响应是否真的返回到实际提出请求的客户端”等类似问题。
任何人都可发起请求
实验到我们的非对称加密算法的公钥出现的问题
为了解决上述问题, 可以使用由数字证书认证机构(CA, CertificateAuthority) 和其相关机关颁发的公开密钥证书。数字证书认证机构处于客户端与服务器双方都可信赖的第三方机构的立场上。 威瑞信(VeriSign) 就是其中一家非常有名的数字证书认证机构。
我们来介绍一下数字证书认证机构的业务流程。 首先, 服务器的运营人员向数字证书认证机构提出公开密钥的申请。 数字证书认证机构在判明提出申请者的身份之后, 会对已申请的公开密钥做数字签名, 然后分配这个已签名的公开密钥, 并将该公开密钥放入公钥证书后绑定在一起。
- 服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端,
- 以进行公开密钥加密方式通信。 公钥证书也可叫做数字证书或直接称为证书。
服务器对于CA应该做什么
服务器生成了自己的非对称算法的公钥和私钥
然后服务器找CA为它颁发证书(现在中,要开店,需要先找工商局办理营业执照)
当我们的客户端发起的请求的时候,服务器把带有机构认证的证书直接给到客户端,我们的客户端会有CA机构的公钥,对证书进行解密
客户端再经过摘要技术算法,(域名为主的信息+公钥信息)得出了新的摘要和证书中的老摘要做对比,说明我们的数据是原始的数据
然后我们的服务端就拿到了服务器的公钥,下面的操作就跟上面实现加密传输对称加密算法的私钥,就可以完成安全进行传输数据
关于客户端怎么知道的公钥的
证明组织真实性的 EV SSL 证书
证书的一个作用是用来证明作为通信一方的服务器是否规范, 另外一个作用是可确认对方服务器背后运营的企业是否真实存在。拥有该特性的证书就是 EV SSL证书(Extended Validation SSLCertificate) 。EV SSL证书是基于国际标准的认证指导方针颁发的证书。 其严格规定了对运营组织是否真实的确认方针, 因此, 通过认证的Web 网站能够获得更高的认可度。持有 EV SSL证书的 Web 网站的浏览器地址栏处的背景色是绿色的, 从视觉上就能一眼辨别出。 而且在地址栏的左侧显示了 SSL
用以确认客户端的客户端证书
认证机构信誉第一
由自认证机构颁发的证书称为自签名证书
如果使用 OpenSSL这套开源程序, 每个人都可以构建一套属于自己的认证机构, 从而自己给自己颁发服务器证书。 但该服务器证书在互联网上不可作为证书使用, 似乎没什么帮助。
独立构建的认证机构叫做自认证机构, 由自认证机构颁发的“无用”证书也被戏称为自签名证书。
浏览器访问该服务器时, 会显示“无法确认连接安全性”或“该网站的安全证书存在问题”等警告消息。
由自认证机构颁发的服务器证书之所以不起作用, 是因为它无法消除伪装的可能性。 自认证机构能够产生的作用顶多也就是自己对外宣称“我是○○”的这种程度。 即使采用自签名证书, 通过 SSL加密之后, 可能偶尔还会看见通信处在安全状态的提示, 可那也是有问题的。 因为就算加密通信, 也不能排除正在和已经过伪装的假服务器保持通信。
值得信赖的第三方机构介入认证, 才能让已植入在浏览器内的认证机构颁布的公开密钥发挥作用, 并借此证明服务器的真实性。
中级认证机构的证书可能会变成自认证证书
多数浏览器内预先已植入备受信赖的认证机构的证书, 但也有一小部分浏览器会植入中级认证机构的证书。对于中级认证机构颁发的服务器证书, 某些浏览器会以正规的证书来对待, 可有的浏览器会当作自签名证书。
HTTPS 也存在一些问题, 那就是当使用 SSL时, 它的处理速度会变慢。
SSL的慢分两种
HTTPS和使用 HTTP 相比, 网络负载可能会变慢 2 到 100 倍。 除去和TCP 连接、 发送 HTTP 请求 • 响应以外, 还必须进行 SSL通信,因此整体上处理通信量不可避免会增加。另一点是 SSL必须进行加密处理。 在服务器和客户端都需要进行加密和解密的运算处理。 因此从结果上讲, 比起 HTTP 会更多地消耗服务器和客户端的硬件资源, 导致负载增强。针对速度变慢这一问题, 并没有根本性的解决方案, 我们会使用SSL加速器这种(专用服务器) 硬件来改善该问题。 该硬件为SSL通信专用硬件, 相对软件来讲, 能够提高数倍 SSL的计算速度。 仅在 SSL处理时发挥 SSL加速器的功效, 以分担负载。
为什么不一直使用 HTTPS
既然 HTTPS 那么安全可靠, 那为何所有的 Web 网站不一直使用HTTPS ?
因为我们对于某些Web资源,我们有只限定给某些人看的需求,所以我们需要进行对访问服务器的用户进行验证
计算机本身无法判断坐在显示器前的使用者的身份。 进一步说, 也无法确认网络的那头究竟有谁。为了弄清究竟是谁在访问服务器, 就得让对方的客户端自报家门。可是, 就算正在访问服务器的对方声称自己是ueno, 身份是否属实这点却也无从谈起。 为确认 ueno 本人是否真的具有访问系统的权限,就需要核对“登录者本人才知道的信息”、 “登录者本人才会有的信息”。核对的信息通常是指以下这些。
HTTP1.1 使用的认证方式
BASIC 认证(基本认证) 是从 HTTP/1.0 就定义的认证方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uQaMbm1E-1681456831822)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\202304100902789.png)]
BASIC 认证虽然采用 Base64 编码方式, 但这不是加密处理。 不需要任何附加信息即可对其解码。 换言之, 由于明文解码后就是用户 ID和密码, 在 HTTP 等非加密通信的线路上进行 BASIC 认证的过程中, 如果被人窃听, 被盗的可能性极高。
另外, 除此之外想再进行一次 BASIC 认证时, 一般的浏览器却无法实现认证注销操作, 这也是问题之一。BASIC 认证使用上不够便捷灵活, 且达不到多数 Web 网站期望的安全性等级, 因此它并不常用。
Base64,顾名思义,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号"+“、”/“一共64个字符的字符集,(另加一个“=”,实际是65个字符,至于为什么还会有一个“=”,这个后面再说)。任何符号都可以转换成这个字符集中的字符,这个转换过程就叫做base64编码。
字符串abc对应3个字节,一共24位,按6位为一组可分为4组,在每组的高位补上00,经过转换,abc 的 base64 编码是 YWJj, 由原来的3个字母变成了4个,所以base64会比原字符串更长。
那问题来了,假设原始字符串不够3个字节,只有一个字节或者两个字节怎么办?
以BC两个字节为例, 按照上面的转换逻辑,经过编码转换,第三个字节只有4位,需要在第三组前后都要加两个0,转换后的字符串是 QkM。 为了凑齐4个字节,还要在末尾补上一个"="号,最后得到的base64编码就是: "QkM=
为弥补 BASIC 认证存在的弱点, 从 HTTP/1.1 起就有了 DIGEST 认证。 DIGEST 认证同样使用质询 / 响应的方式(challenge/response) , 但不会像 BASIC 认证那样直接发送明文密码。
DIGEST 认证提供了高于 BASIC 认证的安全等级, 但是和 HTTPS 的客户端认证相比仍旧很弱。 DIGEST 认证提供防止密码被窃听的保护机制, 但并不存在防止用户伪装的保护机制。DIGEST 认证和 BASIC 认证一样, 使用上不那么便捷灵活, 且仍达不到多数 Web 网站对高度安全等级的追求标准。 因此它的适用范围也有所受限。
SSL 客户端认证的认证步骤
为达到 SSL客户端认证的目的, 需要事先将客户端证书分发给客户端, 且客户端必须安装此证书。
SSL 客户端认证采用双因素认证
基于表单的认证方法并不是在 HTTP 协议中定义的。 客户端会向服务器上的 Web 应用程序发送登录信息(Credential) , 按登录信息的验证结果认证。
根据 Web 应用程序的实际安装, 提供的用户界面及认证方式也各不相同。
认证多半为基于表单认证
Session 管理及 Cookie 应用
基于表单认证的标准规范尚未有定论, 一般会使用 Cookie 来管理Session(会话) 。
基于表单认证本身是通过服务器端的 Web 应用, 将客户端发送过来的用户 ID 和密码与之前登录过的信息做匹配来进行认证的。但鉴于 HTTP 是无状态协议, 之前已认证成功的用户状态无法通过协议层面保存下来。 即, 无法实现状态管理, 因此即使当该用户下一次继续访问, 也无法区分他与其他的用户。 于是我们会使用 Cookie 来管理 Session, 以弥补 HTTP 协议中不存在的状态管理功能。
步骤 1: 客户端把用户 ID 和密码等登录信息放入报文的实体部分,通常是以 POST 方法把请求发送给服务器。 而这时, 会使用 HTTPS通信来进行 HTML表单画面的显示和用户输入数据的发送。
步骤 2: 服务器会发放用以识别用户的 Session ID。 通过验证从客户端发送过来的登录信息进行身份认证, 然后把用户的认证状态与Session ID 绑定后记录在服务器端。向客户端返回响应时, 会在首部字段 Set-Cookie 内写入 SessionID(如 PHPSESSID=028a8c…) 。你可以把 Session ID 想象成一种用以区分不同用户的等位号。然而, 如果 Session ID 被第三方盗走, 对方就可以伪装成你的身份进行恶意操作了。 因此必须防止 Session ID 被盗, 或被猜出。 为了做到这点, Session ID 应使用难以推测的字符串, 且服务器端也需要进行有效期的管理, 保证其安全性。另外, 为减轻跨站脚本攻击(XSS) 造成的损失, 建议事先在 Cookie内加上 httponly 属性。
步骤 3: 客户端接收到从服务器端发来的 Session ID 后, 会将其作为Cookie 保存在本地。 下次向服务器发送请求时, 浏览器会自动发送Cookie, 所以 Session ID 也随之发送到服务器。 服务器端可通过验证接收到的 Session ID 识别用户和其认证状态。
除了以上介绍的应用实例, 还有应用其他不同方法的案例。另外, 不仅基于表单认证的登录信息及认证过程都无标准化的方法,服务器端应如何保存用户提交的密码等登录信息等也没有标准化。通常, 一种安全的保存方法是, 先利用给密码加盐(salt)的方式增加额外信息, 再使用散列(hash) 函数计算出散列值后保存。 但是我们也经常看到直接保存明文密码的做法, 而这样的做法具有导致密码泄露的风险。
具体存在那些缺陷的例子
Google 在 2010 年发布了 SPDY(取自 SPeeDY, 发音同 speedy) , 其开发目标旨在解决 HTTP 的性能瓶颈, 缩短 Web 页面的加载时间(50%) 。SPDY - The Chromium Projects
Ajax(Asynchronous JavaScript and XML, 异 步 JavaScript 与 XML技术) 是一种有效利用 JavaScript 和 DOM(Document Object Model, 文档对象模型) 的操作, 以达到局部 Web 页面替换加载的异步通信手段。
一旦服务器端有内容更新了, Comet 不会让请求等待, 而是直接给客户端返回响应。 这是一种通过延迟应答, 模拟实现服务器端向客户端推送(Server Push) 的功能。
通常, 服务器端接收到请求, 在处理完毕后就会立即返回响应, 但为了实现推送功能, Comet 会先将响应置于挂起状态, 当服务器端有内容更新时, 再返回该响应。 因此, 服务器端一旦有更新, 就可以立即反馈给客户端。
内容上虽然可以做到实时更新, 但为了保留响应, 一次连接的持续时间也变长了。 期间, 为了维持连接会消耗更多的资源。 另外, Comet也仍未解决 HTTP 协议本身存在的问题。
SPDY的目标
SPDY 没有完全改写 HTTP 协议, 而是在 TCP/IP 的应用层与运输层之间通过新加会话层的形式运作。 同时, 考虑到安全性问题, SPDY 规定通信中使用 SSL。
SPDY 以会话层的形式加入, 控制对数据的流动, 但还是采用 HTTP建立通信连接。 因此, 可照常使用 HTTP 的 GET 和 POST 等方 法、Cookie 以及 HTTP 报文等。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ShOdYRwI-1681456831826)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\image-20230411191754894.png)]
使用 SPDY 后, HTTP 协议额外获得以下功能。
多路复用流
赋予请求优先级
压缩 HTTP 首部
推送功能
服务器提示功能
浏览器进行全双工通信的
利用 Ajax 和 Comet 技术进行通信可以提升 Web 的浏览速度。 但问题在于通信若使用 HTTP 协议, 就无法彻底解决瓶颈问题。 WebSocket网络技术正是为解决这些问题而实现的一套新协议及 API。
当时筹划将 WebSocket 作为 HTML5 标准的一部分, 而现在它却逐渐变成了独立的协议标准。 WebSocket 通信协议在 2011 年 12 月 11 日,
被 RFC 6455 - The WebSocket Protocol 定为标准。
WebSocket, 即 Web 浏览器与 Web 服务器之间全双工通信标准。 其中, WebSocket 协议由 IETF 定为标准, WebSocket API 由 W3C 定为标准。 仍在开发中的 WebSocket 技术主要是为了解决 Ajax 和 Comet里 XMLHttpRequest 附带的缺陷所引起的问题。
一旦 Web 服务器与客户端之间建立起 WebSocket 协议的通信连接,之后所有的通信都依靠这个专用协议进行。 通信过程中可互相发送JSON、 XML、 HTML或图片等任意格式的数据。
由于是建立在 HTTP 基础上的协议, 因此连接的发起方仍是客户端,而一旦确立 WebSocket 通信连接, 不论服务器还是客户端, 任意一方都可直接向对方发送报文。
WebSocket 协议的主要特点
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uW5jCqUF-1681456831827)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\image-20230411193502276.png)]
目前主流的 HTTP/1.1 标准, 自 1999 年发布的 RFC2616 之后再未进行过改订。 SPDY 和 WebSocket 等技术纷纷出现, 很难断言 HTTP/1.1仍是适用于当下的 Web 的协议。
HTTP/2.0 的目标是改善用户在使用 Web 时的速度体验。 由于基本上都会先通过 HTTP/1.1 与 TCP 连接, 现在我们以下面的这些协议为基础
HTTP Speed + Mobility 由微软公司起草, 是用于改善并提高移动端通信时的通信速度和性能的标准。 它建立在 Google 公司提出的 SPDY与 WebSocket 的基础之上。
压缩 | SPDY、 Friendly |
---|---|
多路复用 | SPDY |
TLS 义务化 | Speed+ Mobility |
协商 | Speed+ Mobility, Friendly |
客户端拉曳(Client Pull) /服务器推送 (Server Push) | Speed+ Mobility |
流量控制 | SPDY |
WebSocket | Speed+ Mobility |
注: HTTP Speed + Mobility 简写为 Speed + Mobility, Network-Friendly HTTP Upgrade 简写为 Friendly。
在 HTTP/2 中,有两个非常重要的概念:帧(frame)和流(stream)。
帧(frame)
HTTP/2 中数据传输的最小单位,因此帧不仅要细分表达 HTTP/1.x 中的各个部分,也优化了 HTTP/1.x 表达得不好的地方,同时还增加了 HTTP/1.x 表达不了的方式。 每一帧都包含几个字段,有length、type、flags、stream identifier、frame playload等,
- 其中type 代表帧的类型,在 HTTP/2 的标准中定义了 10 种不同的类型, HEADERS frame 和 DATA frame。此外还有:
PRIORITY
(设置流的优先级)RST_STREAM
(终止流)SETTINGS
(设置此连接的参数)PUSH_PROMISE
(服务器推送)PING
(测量 RTT)GOAWAY
(终止连接)WINDOW_UPDATE
(流量控制)CONTINUATION
(继续传输头部数据)在 HTTP 2.0 中,它把数据报的两大部分分成了 header frame 和 data frame。也就是头部帧和数据体帧。
流(stream)
流: 存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数 ID。 HTTP/2 长连接中的数据包是不按请求-响应顺序发送的,一个完整的请求或响应(称一个数据流 stream,每个数据流都有一个独一无二的编号)可能会分成非连续多次发送。它具有如下几个特点:
- 双向性:同一个流内,可同时发送和接受数据。
- 有序性:流中被传输的数据就是二进制帧 。帧在流上的被发送与被接收都是按照顺序进行的。
- 并行性:流中的 二进制帧 都是被并行传输的,无需按顺序等待。
- 流的创建:流可以被客户端或服务器单方面建立, 使用或共享。
- 流的关闭:流也可以被任意一方关闭。
- HEADERS 帧在 DATA 帧前面。
- 流的 ID 都是奇数,说明是由客户端发起的,这是标准规定的,那么服务端发起的就是偶数了
HTTP 协议的初始版本中, 每进行一次 HTTP 通信就要断开一次 TCP连接。
Keep-Alive
还是存在如下问题:
HTTP 管线化仍旧有阻塞的问题,若上一响应迟迟不回,后面的响应都会被阻塞到。
多路复用代替原来的序列和阻塞机制。所有就是请求的都是通过一个 TCP 连接并发完成。因为在多路复用之前所有的传输是基于基础文本的,在多路复用中是基于二进制数据帧的传输、消息、流,所以可以做到乱序的传输。多路复用对同一域名下所有请求都是基于流,所以不存在同域并行的阻塞。多次请求如下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wp3Ku5hK-1681456831828)(C:\Users\lsc07\Desktop\学习资料\19typora笔记\5计算机网络\HTTP.assets\image-20230411195736520.png)]