【JavaEE】HTTP协议(HTTPS协议)和TOMCAT

1.❤️❤️前言~🥳🎉🎉🎉

Hello, Hello~ 亲爱的朋友们👋👋,这里是E绵绵呀✍️✍️。

如果你喜欢这篇文章,请别吝啬你的点赞❤️❤️和收藏📖📖。如果你对我的内容感兴趣,记得关注我👀👀以便不错过每一篇精彩。

当然,如果在阅读中发现任何问题或疑问,我非常欢迎你在评论区留言指正🗨️🗨️。让我们共同努力,一起进步!

加油,一起CHIN UP!💪💪

🔗个人主页:E绵绵的博客**
📚所属专栏:**

1. JAVA知识点专栏

深入探索JAVA的核心概念与技术细节

2.JAVA题目练习****

实战演练,巩固JAVA编程技能

3.c语言知识点专栏****

揭示c语言的底层逻辑与高级特性

4.c语言题目练习****

挑战自我,提升c语言编程能力

5.Mysql数据库专栏

了解Mysql知识点,提升数据库管理能力

6.html5知识点专栏

学习前端知识,更好的运用它

7.css3知识点专栏

在学习html5的基础上更加熟练运用前端

8.JavaScript专栏

在学习html5和css3的基础上使我们的前端使用更高级、

9.JavaEE专栏

学习更高阶的Java知识,让你做出网站

📘 持续更新中,敬请期待 ❤️❤️

2.HTTP协议

HTTP协议介绍

我们现在要讲一下应用层的其他协议:HTTP协议。

HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的 应用层协议,我们在生活中经常用到。


我们举两个经典应用场景:

1.网页和服务器之间的交互

我们平时打开一个网站, 就是通过 HTTP 协议来传输数据的.

当我们打开了一个b站,输入了一串网址的时候,此时就是在基于通过HTTP的方式和b站的服务器进行通信。浏览器就给b站的服务器发送了一个 HTTP 请求, b站的服务器返回了一个 HTTP 响应.

这个响应结果被浏览器解析之后, 就展示成我们看到的页面内容. (这个过程中浏览器可能会给服务器发送多个 HTTP 请求, 服务器会对应返回多个响应, 这些响应里就包含了页面 HTML, CSS, JavaScript, 图片,字体等信息)

所谓 "超文本" 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些其他的资源, 比如图片, 视频, 音频等二进制的数据

2.手机app与服务器之间的交互

比如打开一个外卖软件,加载一些食品列表数据以及下单操作,这些过程也是通过HTTP来完成的。它跟网页与服务器之间的交互一样。


虽然HTTP的作用很大,应用很广,但是实际开发中,不一定是真的直接使用HTTP,更大的概率是使用HTTPS(本质上是HTTP引入的加密层,s指安全,即叫做"超文本安全传输协议")。很少直接使用HTTP
HTTP 往往是基于传输层的 TCP 协议实现的. (HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP实现)

目前我们主要使用的还是 HTTP1.1 和 HTTP2.0 . 该文章主要讲述HTTP1.1

Fiddler抓包

​当我们在浏览器中输入一个 "网址",此时浏览器就会给对应的服务器发送一个HTTP 请求。 对方服务器收到这个请求之后,经过计算处理, 就会返回一个 HTTP 响应。也就是典型的"一问一答"模式,请求和响应是一一对应的。

事实上, 当我们访问一个网站的时候, 可能涉及不止一次的 HTTP 请求/响应的交互过程,会有超多的请求。那么要想进一步的理解HTTP协议工作过程,以及理解HTTP的报文格式,就需要用到"抓包工具",这样才能更好了解HTTP协议
HTTP抓包工具种类有很多,比如 wireshark,它功能非常强大,使用起来也比较复杂的,用这个也能抓 HTTP, 但是不太方便。

这里我们推荐使用Fiddler,它是专门抓HTTP的工具
当我们下载好Fiddler后(下载我就不教了),我们打开该软件就可以直接开始抓包了

页面左侧包含你主机上所有进程http请求/响应数据,右侧是对左侧某个数据包双击之后的一个详细信息


一个网页打开的时候,往往不只是和服务器进行一次操作,是很多次操作,比如我们对csdn来进行抓包,这些结果都是浏览器打开csdn的时候,给csdn发送的http/https的请求数据。这里很多数据我们主要关注的是蓝色的数据,其他可以不用关心


现在我们就可以观察蓝色数据的报文格式,右侧上方的是请求报文,我们点击raw则可以观察到原始的请求数据,如果觉得字体小了还可以点击view in notepad


右侧下方则是响应报文,这里有个疑问,为什么看不懂该报文,这是因为此时它是二进制协议报文,所以看不懂数据。

但是HTTP 协议是文本格式的协议,TCP, UDP, IP才是二进制格式的协议,这里为什么好端端的文本格式协议变为二进制格式的协议(文本格式协议和二进制格式协议区别在于看不看得懂内容),这是因为HTTP 响应通常会被压缩为二进制格式的协议,压缩之后体积变小,传输的时候节省网络带宽(一台服务器最贵的就是网络带宽)

此时想要看清楚原本的内容我们只需点击黄色的内容即可解压,变为文本格式协议内容,之后的操作就跟请求报文时一样,不多说了。


除此以外还有一个小技巧:可以使用 ctrl + a 全选左侧的抓包结果, delete 键清除所有被选中的结果
但这里要注意一点,现在用的大多都是hhtps,而目前的fidder只能抓取http,我们要设置一下才能捕获https。

点击Options里面的HTTPS选项,然后将里面的选项全部打勾


这里值得注意的是,它会出现一个提示框,提示你是否安装一个证书,这里一定要选择是,如果不小心选择否,重装Fiddler

然后OK就可以开始抓HTTPS的包了。
对于Fiddler其实相当于一个 "代理服务器".

浏览器访问 csdn.com 时, 会把 HTTP 请求先发给 Fiddler, Fiddler 再把请求转发给 csdn 的服务器.当 csdn 服务器返回数据时, Fiddler 拿到返回数据, 再把数据交给浏览器.

因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节, 都是非常清楚的,所以才能抓取包。

代理也有正向代理和反向代理,可以简单的理解为帮助客户端"跑腿"的为正向代理,帮助服务器"跑腿"的为反向代理。(反向代理我们这里先不说)


除了 fiddler 之外, 有的程序也是代理,如加速器和vpn。这些代理程序之间,可能是冲突的。
所以使用 fiddler抓包前, 一定要检査关闭之前的代理软件,否则可能会抓包不成功。

HTTP协议格式

学习一个协议我们肯定要知道它的格式,HTTP协议格式跟其他协议不同,**它的请求报文格式和响应报文格式是不同的,**我们可以通过刚学的Fiddler去抓包看下请求和响应的内容。


从以上内容可以看出两者格式确实不同,那么下面我们来详细介绍下它们的格式。

请求报文格式

请求报文格式由首行,请求头(header),空行,正文(body) 组成

首行------URL

HTTP 请求的第一行.有三个部分信息,三个部分使用 空格 分割,下图是一个经典例子,我们来分析下:

1.GET, HTTP 请求的"方法"(method)
2.URL 唯一资源定位符,描述了一个资源在网络上的位置。
3.版本号 HTTP/1.1

这里要重点讲述的由第一个信息:方法 和 第二个信息:URL ,我们先讲URL
平时我们俗称的 "网址" 其实就是说的 URL (Uniform Resource Locator 统一资源定位符)

URL的详细规则由因特网标准RFC1738 进行了约定,其详细格式如下:


1.协议方案名: 常见的有 http 和 https,告诉你是哪个协议 也有其他的类型.(例如访问 mysql 时用的jdbc:mysql )

2.登陆信息: 现在的网站进行身份认证一般不再通过 URL 进行了, 一般都会省略,属于上古时期的方式,现在都没有人这么进行登录了

3.服务器地址: 要访问的服务器是哪个,此处是一个 "IP地址/域名", 域名会通过 DNS 系统解析成一个具体的 IP 地址

4.端口号: 上面的 URL 中端口号可以被省略, 当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口, (例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口)

5.带层次的文件路径: 描述了要访问服务器的哪个资源,一个服务器可提供很多资源供外界访问,比如web服务器(网站)就可能会包含很多不同的网页,就可以通过这里的路径区分不同的网页。

6.查询字符串(query string): 本质是一个键值对结构,它以?开头 , 键值对之间使用 & 分隔, 键和值之间使用 = 分隔,1个 url 中的 query string 里可以包含 N 个键值对,甚至可能更长。查询字符串是程序猿自定义的,不像 header 中的键值对是标准规定的。我们可以通过这样的方式来自定制传输我们需要的信息给服务器。(请求报文中的body作用也是如此,自定制传输我们需要的信息,之后在讲方法时我们会讲)

这里还要提一点,对于 query string 来说,如果 value 部分要包含特殊符号或者中文字符的话,往往需要进行 urlencode 操作,urlencode 本质上是一种转义字符,如++进行urlencode操作后就是%2B%2B

查询c++的网址我们也能看到有该编码出现

为什么要urlencode操作呢?因为像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.query string里面的value部分,一旦也包含这些符号不就乱套了吗,就会使url的解析出现问题,如果不处理好,有些浏览器就可能会解析失败,导致请求无法正常进行.

另外我们在游览器网址上可能看到该现象:有中文汉字出现,那这是什么情况?

实际上,如果把这串url复制粘贴到记事本,那么就又回到了urlencode编码状态,这是因为浏览器为了让用户看起来更加直观,所以就按照转码之前的方式进行显示的,实际上网络传输的请求依旧是转码之后的状态。

7.片段标识符:有的网页内容比较长,就可以分成多个"片段",通过片段标识符,就可以完成页面内部的跳转,这个一般应用于技术文档,普通网站都不会存在片段标识符

首行------方法

方法的种类有以下几种:


对于这些方法,最常用的是Get和Post方法,其他方法很少使用。

Get方法

GET 是最常用的 HTTP 方法,常用于获取服务器上的某个资源.网络上大部分请求都是GET

方法。

GET请求中程序员自定制想要传输的信息都存放在query string中,里面不包含body(body也是用于自定制传输信息)

Post方法

POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆,上传文件)

GET请求中程序员自定制想要传输的信息都存放在body中,url中不包含query string

Get与Post的区别

这是一个经典的面试题:

开篇, 我们先盖棺定论,GET 和 POST 没有本质区别(双方甚至可以替换对方的场景)这是因为这些 HTTP 请求,最初的初心就是为了表示不同的"语义",对于语法规定并没规定其有什么本质不同,所以实际上程序员如何使用,可以更加随意,因为语法上没有严格规定不同,所以就算乱用也不会报错。(GET和POST没有本质区别其实也可以说上述所有方法就没有本质区别,可以乱着用)

虽然GET和POST没有本质区别,但使用习惯上我们程序员还是普遍达成了一个共识,使它们存在一些差异:

1.GET 经常是把自定制传递给服务器的数据放到 query string 中; POST 则是经常放到 body 中.(使用习惯上最大的差别)
2.语义上的差异: GET用来获取数据,POST 用来提交数据

上述这些习惯虽然我们可以不遵循,但还是建议大家遵守上述的约定俗称的习惯,因为大家都用该习惯。
除此以外,还有一些网上说的差异,实际上是错误的:

1.GET 请求能传递的数据量有上限,POST 传递的数据量没有上限.
这个说法是一个"历史遗留"早期版本的浏览器(硬件资源非常匮乏),针对 GET 请求的 URL 的长度做出了限制,实际上,RFC 标准文档中并没有明确规定 URL 能有多长.....目前的浏览器和服务器的实现过程中, URL 可以非常长的.(甚至说可以使用 URL 传递一些图片这样的数据)

2.GET 请求传递数据不安全,POST 请求传递数据更安全

依据是: 如果使用 GET 请求来实现登录,点击登录的时候,就会把用户名和密码放到 u 中,进一步的显示到浏览器地址栏里,不就被别人看到了吗,相比之下, POST 则是在 body 中,不会在界面上显示出来,所以就更安全,这很显然不对

我们通常说的"安全"指的是你传递的数据,不容易被黑客获取或者被黑客获取到之后不容易被破解,当不放在界面上显示,并不能体现它很安全,万一加密不严格,一下子就被黑客捕获到了,这不就是不安全。所以安全性和 选择get还是post无关,关键在于加密。

3.GET 只能给服务器传输文本数据. POST 可以给服务器传输文本和二进制数据.

(1)GET 也不是不能使用 body (body 中是可以直接放二进制的)
(2)GET 也可以把 二进制的数据进行 base64 转码(变为文本数据), 放到 ur 的 query string 中

4. GET 请求是幂等的. POST 请求不是幂等的.
幂等是指输入相同的内容, 输出是稳定的, GET 和 POST 具体是否是幂等,取决于代码的实现,
1个典型的 GET 不幂等的情况: 搜狗的广告搜索

广告数据就是通过 GET 请求获取的.这些 GET 请求设计的时候一定是不幂等的.这里出哪些广告, 广告的顺序,背后涉及到一系列复杂的逻辑

5.GET 请求可以被浏览器缓存,POST 不可以被缓存

幂等性的延续,如果请求是幂等,自然就可以缓存,不是幂等就不行。所以Get请求也有可能不被缓存,post也可能被缓存

6. GET 请求可以被浏览器收藏夹收藏,POST 不能被浏览器收藏,这个同样是错误的。

请求头(header)

它是一个键值对结构的数据,每个键值对都是独占一行的,键和值之间, 使用 :空格 来区分

键值对之间以换行符分割。

header中的键值对跟query string不同,query string中的键值对是程序猿自己定义的,而header中的键值对都是标准规定的内容。

header中包含的键值对有很多,但是大部分都不关键,主要介绍几个关键的。

HOST

表示目标服务器的域名或 IP 地址。

Conte-Length

表示 body 中的数据长度,单位是字节,一旦有了body就需要知道body的长度,才能知道一个完整的http请求。

由于HTTP是基于TCP,那么这里就会谈到粘包问题,前面我们谈到的粘包问题有两种解决方案,一个是指定分隔符,一个是指定长度。如果是GET请求没有body,通过空行;如果是POST请求有body,通过空行找到body的开始,通过Conte-Length找到body的介绍位置。

Content-Typent

表示请求报文中body内部的数据类型,有以下三种数据类型

1.json,具体类型为 application/json

2.form表单的格式,具体类型为application/x-www-form-urlencoded:form

3.form-data 的格式,multipart/form-data: form

User-Agent (简称 UA)

UA里的信息主要有两个部分:浏览器版本,操作系统版本

在以前UA主要是描述你用啥样的设备,啥样的浏览器。对于现在来说作用不是很大了,现在主要是区分该设备是pc端还是移动端

Referer

表示当前页面是从哪个页面跳转过来的.

如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的.

在搜狗浏览器搜索信息时(页面跳转):此处的Referer就是表示从搜狗主页跳转过来的。
用途:对于网页上面的广告,用户点击一次搜狗就能挣钱(按点击计费),那么在一个月之内某个广告被点击的次数就需要进行统计,搜狗需要统计,广告主也需要统计。每次点击就会把请求发送到搜狗服务器上,搜狗的服务器就可以记录一条日志(日志就是打印)。广告主这边也会有服务器,每次收到请求就会记录一条日志,统计日志的数目即可。广告主可能有多渠道投放,就需要对不同的渠道进行区分,此时就可以通过Referer进行区分,是从搜狗跳转过来的Referer就是搜狗的域名,从百度跳转过来的Referer就是百度的域名。

有没有一种可能,存在某个人把访问广告主服务器的请求的 referer 给修改了呢?运营商(移动联通等)完全有能力做这个事情,修改成别人的refer,自己再赚一笔,在2015年存在非常多这样的现象,这叫做运营商劫持。运营商劫持每天都会对互联网公司造成巨大损失,公司就从技术上进行"反制",HTTPS就是重要的反制手段,HTTPS直接针对HTTP请求中的内容进行加密,这样就不会再被修改了(关于https如何加密,后序介绍)

Cookie 可以认为是 浏览器 在本地存储数据的一种机制。

在程序运行过程中,需要一些数据在浏览器这边存储,并且在后续请求的时候数据可能需要再发给服务器,所以我们就利用cookie存储这些数据,如上次登陆时间.上次访问时间.用户的身份信息,累计的访问次数。

实际上更容易想到的是,把这样的数据直接存储到本地文件中,但是实际上不可行的.浏览器为了考虑到安全性,禁止网页直接访问你的电脑的文件系统(怕你访问某个网站,结果网页里有病毒,把你硬盘上的所有学习资料都给删掉了),网页代码中也就无法直接生成一个硬盘的文件来储数据了.
为了保证安全性,又能进行存储数据,于是就引入了 Cookie,cookie内部只能存储键值对,键值对之间,使用;分割 键和值使用 =分割,如下

这些 内容 就是浏览器本地存储的 cookie,都会在后续请求服务器的时候,把这些内容给代入到请求中传给服务器,服务器通过 Cookie 的内容做一些逻辑上的处理

cookie内部的内容都是程序猿自定义的,咱们作为外人不能理解。后续咱们自己写网站,也可以自定义了

Cookie 往往是将服务器返回的数据进行存储,存储的都是临时数据,Cookie 存储到浏览器所在主机的硬盘上,并且是按照域名为单位来存储的,意思就是每个域名都可以存自己的 Cookie,彼此之间不影响。

对于cookie目前只是初步了解,后续会更详细的讲述。


对于剩下的空行和body:

空行是作为请求头的结束标记

而body我们之前也讲过了,是我们自定义要传输的信息,并且post中存在,get并不存在body

响应报文格式

首行------状态码

响应报文格式包括

1.版本号 如HTTP/1.1

2.状态码(如200) 描述了请求的结果

3.状态码描述(如OK)


下图是一个很好的例子


这里主要介绍一下响应报文里面的 状态码 和状态码描述,它们描述了这次HTTP请求是否成功以及失败的原因


这里的状态码很多,只需要掌握以下常见的状态码即可
信息类(1xx)

这里的状态码大体意思就是表示请求已被接收,但需要客户端继续发送请求,很少用到这里的状态码。
成功类(2xx)

这里的状态码表示请求已成功处理,200 ok 是我们最常见的一个状态码,表示访问成功.
重定向类(3xx)

3xx 表示 重定向。重定向指的是请求中访问的是 A 这样的地址,响应返回了一个重定向报文,告诉你应该要访问 B 地址

很多时候,页面跳转,就可以通过重定向来实现,还有的时候,某个网站服务器迁移了. IP/域名变了,就可以给旧的地址挂一个重定向响应,访问旧地址的用户就自动跳转到新的地址

这里有两个常见的状态码

301 Moved Permanently(永久重定向)

  • 含义:请求的资源已永久移动到新的位置。

302 Found(临时重定向)

  • 含义:请求的资源临时移动到新的位置。

客户端错误类(4xx)

  • 表示客户端的请求有误,服务器无法处理。

  • 常见状态码

    • 400 Bad Request:请求格式错误。

    • 401 Unauthorized:请求需要用户认证。

    • 403 Forbidden:服务器拒绝请求(权限不足)。

    • 404 Not Found:请求的资源不存在。

    • 405 Method Not Allowed:请求方法不被允许(如 GET 请求不允许使用 POST)。

服务器错误类(5xx)

  • 表示服务器在处理请求时发生了错误。

  • 常见状态码

    • 500 Internal Server Error:服务器内部错误。

    • 501 Not Implemented:服务器不支持请求的方法。(get或者post)

    • 503 Service Unavailable:服务器暂时不可用(如过载或维护)。

响应头

响应头 (header)跟请求头结构一样,键值对内容也跟请求头大差不差的。

唯一要说的点就是content-typent,由于这是响应报文,响应报文里绝对会有body内容,body里的内容可能比较长, 会有多种格式,如HTML, CSS, JS, JSON, XML, 图片, 字体, 视频, 音频等,比请求报文里的body种类多好多。


除此以外,空行依旧是响应头的结束标志,body我们响应头该提的都提了,这里也不多说了

3.如何构造HTTP请求

在讲完HTTP协议的报文结构后,我们接下来就要去了解下面两个问题

如何让客户端构造一个 HTTP 请求?

如何让服务器处理一个 HTTP 请求 ?

处理请求涉及到Servlet/Spring ,它非常重要,要讲清楚如何处理要花非常多的时间,所以这里我们就先只讲如何构造一个HTTP请求。
首先我们能直接在浏览器 地址栏 输入 url, 此时构造了一个 GET 请求, 又或者在htm| 中, 一些特殊的 htm| 标签, 可能会构造 GET 请求,比如像 img, a, link, script。

如果通过代码的话,我们能通过form或者是ajax的方式去构造,这里都是前端代码,就不说了

除此以外还有一种代码的方式,通过Java scoket构造HTTP请求,所谓的 "发送 HTTP 请求", 本质上就是按照 HTTP 的格式往 TCP Socket 中写入一个字符串. 所谓的 "接受 HTTP 响应", 本质上就是从 TCP Socket 中读取一个字符串, 再按照 HTTP 的格式来解析. 我们基于 Socket 的知识, 完全可以构造出一个简单的 HTTP 客户端程序, 用来发送各种类型的 HTTP 请求。
**除了这些以外,我们还能通过第三方软件去快捷生成HTTP请求,这是最方便的,**这里我们推荐用postman软件,极其好用

以下是其下载和使用教程文章 Postman安装使用教程(详解)-CSDN博客 ,一般构造请求都用它。

4.HTTPS协议

当前网络上,主要都是 HTTPS 了,很少能见到 HTTP
实际上 HTTPS 也是基于 HTTP,前面讲过的 HTTP 的各个方面的内容, 对于 HTTPS 同样适用,报文结构都是一样的。只不过 HTTPS 在 HTTP 的基础之上, 引入了"加密"机制.
引入 HTTPS 防止你的数据被黑客篡改(尤其是反针对 运营商劫持)
加密机制是什么?
明文:要传输的原始数据

密文:经过加密之后得到的数据
密钥:进行加密和解密过程的重要道具

加密就是把明文(要传输的信息)进行一系列变换,生成密文.

解密就是把密文再进行一系列变换,还原成明文.

在这个加密和解密的过程中,往往需要一些数据才能进行转换,这样的数据称为密钥
既然要保证数据安全, 就需要进行 "加密".

网络传输中不再直接传输明文了, 而是加密之后的 "密文".

加密的方式有很多, 但是整体可以分成两大类: 对称加密非对称加密
对称加密其实就是通过同一个 "密钥" , 把明文加密成密文, 并且也能把密文解密成明文。


非对称加密要用到两个密钥, 一个叫做 "公钥", 一个叫做 "私钥". (私钥是自己必须严格保密的钥匙,公钥是公开发布给大家的钥匙)

  • 通过公钥对明文加密, 变成密文
  • 通过私钥对密文解密, 变成明文

也可以反着用

  • 通过私钥对明文加密, 变成密文
  • 通过公钥对密文解密, 变成明文

公钥和私钥是配对的. 它最大的缺点就是运算速度非常慢,比对称加密要慢很多.但安全性高

HTTPS保证自己的安全性过程

在讲完上述加密概念后,我们就能去讲述HTTP如何保证自己的安全性了

引入对称加密

HTTPS会对数据进行对称加密, 即使数据被截获, 由于黑客不知道密钥是啥, 因此就无法进行解密, 也就不知道请求的真实内容是啥了.


但事情没这么简单. 要想进行对称加密,就需要客户端和服务器都具有同一个对称密钥,服务器同一时刻其实是给很多客户端提供服务的. 这么多客户端, 每个人用的秘钥都必须是不同的(如果是相同那密钥就太容易扩散了, 黑客就也能拿到了). 因此服务器就需要维护每个客户端和每个密钥之间的关联关系,这是个极其累的事,如果还要服务器再生成密钥的话就太负载了。

这个时候比较理想的做法, 让每个客户端生成一个密钥,在客户端和服务器建立连接的时候, 传输给服务器让服务器也有。
但是如果直接把密钥明文传输, 那么黑客也就能获得密钥了,此时后续的加密操作就形同虚设了。

因此密钥的传输也必须加密传输!

但是要想对密钥进行对称加密, 就仍然需要先协商确定一个 "密钥的密钥". 这就无限套娃了. 此时密钥的传输再用对称加密就行不通了,我们就选择用非对称加密进行密钥的传输。

引入非对称加密

服务器会自己生成一对公钥和私钥,并且把自己生成的公钥传输给客户端,私钥还是自己来持有。

接下来客户端会对自己的对称密钥(每个客户端生成自己的,客户端之间不知道别人的对称密钥是啥),比如上图的这个客户端生成的对称密钥时六个8,此时这个六个8不会明文传输,通过刚才从服务器拿到的公钥,来针对对称密钥进行加密,再把对称密钥的密文传输给服务器,这样服务器就知道了对称密钥是什么。

此时黑客拿到对称密钥的数据之后,是无法解密的,使用公钥加密,就得使用对应的私钥来进行解密,黑客能轻松拿到公钥,而拿不到私钥,这样是解密不了数据的。

我们要注意一个服务器只会生成一对公钥和私钥(意味着所有和它连接的客户端都是用同一套公钥进行加密)
既然已经引入了非对称加密,为啥还需要引入对称加密呢?直接使用非对称加密,来完成所有业务数据的加密传输即可
这是因为进行非对称加密/解密,运算成本是比较高的.运算速度也是比较低的,对称加密运算成本低, 速度快.
使用非对称加密kkkk,只是用来进行这种关键环节(传输密钥)(一次性的工作,体积也不大),成本就比较可控后续要传输大量的业务数据,都使用效率更高的对称加密,比较友好的做法.

如果业务数据都使用非对称加密,整体的传输效率就会大打折扣了.
注意:上述流程看起来很美好,但是黑客依然能获取到原始数据,通过中间人攻击去获取。

中间人攻击问题

下面我们说下中间人攻击的流程:

客户端访问服务器(黑客冒充的),请求公钥,服务器就会生成一对公钥和私钥(提前生成好的),在此我们称为pub,pri,然后把公钥(pub)返回给黑客
这时就到了关键环节:黑客可以自己生成出一对公钥(pub2)和私钥(pri2),黑客就会把自己的公钥(pub2)返回给客户端,客户端就无法区分出当前的pub2是不是服务器最开始返回的公钥,是不是被中间人掉包了的公钥,客户端就只能选择相信,客户端就会拿着pub2针对对称密钥进行加密,并且发送给服务器(黑客),此时黑客就会拿着pir2针对刚才收到的pub2加密的数据进行解密,从而拿到这里的对称密钥,黑客继续把拿到的对称密钥,使用服务器的公钥pub再次加密发送给服务器,服务器就会使用自己的私钥进行解密,此处肯定会解密成功,拿到对称密钥,接下里意味着客户端和服务器就会继续使用这个对称密钥来完成后续的业务数据加密,此时对称密钥已经泄露出去了

上述过程,黑客面对服务器的时候,扮演客户端的角色,面对客户端的时候,扮演服务器的角色,那么客户端和服务器都不知道黑客的存在,这样就很神秘的泄露出去了。

引入证书

上面讲到,客户端无法区分拿到的公钥是否为服务器返回的公钥,还是说其他人伪造的公钥。那么客户端如果能做出区分,当前的公钥是否为服务器返回的公钥,中间人攻击就不攻自破了。

为了解决该问题,我们引入第三方的可以被大家都信任的"公证机构",公证机构说这个公钥是正确的,不是被伪造的,我们就是可以信任的。所有的服务器在上线自己的网站的时候,都要先去第三方公证机构申请一个证书(此处的证书并不是纸质的,而是数字证书,可理解为一串字符串数据),这个证书包含:

发证机构
有效期
服务器的公钥
证书持有者
持有者网站的主域名
数字签名

这个数字签名可理解为一个加密之后的校验和,校验和是基于CRC/MD5等方式,把证书的其他内容的每个字节都带入计算一遍,最终得到的一串字符串,然后针对校验和进行非对称加密的方式进行加密,那么是谁的私钥进行加密的呢?

公证机构自己会生成一对公钥和私钥(和服务器的公钥私钥不一样),公证机构会自己持有私钥,而每个电脑的操作系统都会内置公证机构的公钥,公证机构会拿自己的私钥针对证书数据的校验和进行加密,得到数字签名。


在申请了证书后,我们就不再发送公钥了,而是直接发送证书(证书里面包含公钥)

客户端拿到了证书,也就拿到了证书中的公钥,客户端就需要验证这个公钥是否是服务器最初的公钥(是否是被黑客篡改了)

这个过程就称为证书的校验,如何进行校验?

此时,客户端拿到了数字签名,就可以通过操作系统内置的公证机构的公钥进行解密了,得到最初的校验和,客户端再重新计算一遍这里的校验和,和解密出来的校验和进行对比,如果校验和一致,就可以认为证书没有被篡改过,公钥就是可信的
在上述机制下,黑客就无法对证书内容进行篡改了,即使篡改,也很容易被发现.
当黑客收到证书之后,如果直接修改里面的公钥,替换成自己的,客户端在进行证书校验的时候,就会发现校验和不一致了,客户端就可以认为是篡改过了.(客户端这边往往就会弹出一些对话框来警告用户,存在安全风险)

那么黑客在替换公钥时,同时替换掉数字签名是否可以呢?

在算出自己的校验和时,针对校验和加密,需要使用公证机构的私钥才能进行.黑客没有这个私钥.如果黑客拿自己的私钥加密,客户端也就无法使用公证机构的公钥解密了公证机构的公钥是客户端系统自带的,黑客也无法替换 (如果不对校验和进行加密,黑客还真可能得逞
结合上述过程,证书就是可信的,通过了校验,就说明公钥就是服务器原始的公钥了,完美解决了中间人攻击问题


所以https是通过以下三点相结合保证 https 的安全性:
1.对称加密,加密业务数据

2.非对称加密,加密对称密钥
3.使用证书,校验服务器的公钥

这是一道经典的面试题,我们要深刻的理解它。

对于上述的加密流程,是由SSL这样的协议来规定的(SSL 后来改名成了TLS),它不仅仅用于 HTTPS 中,也被用到了很多其他的场景里.

5.TOMCAT

我们上面已经学过了HTTP协议,知道了HTTP协议就是HTTP客户端和HTTP服务器之间的交互数据的格式,知道了想要实现一个HTTP服务器我们可以通过Java Socket来实现。

但有没有什么现成的服务器呢?Tomcat就是基于Java实现的一个开源的、免费的、最广泛使用的一个HTTP服务器,基于tomcat我们程序员可以对它进行修改自己实现一个想要的服务器。(Tomcat 是一个基于 java 实现的"绿色软件",只要解压缩, 就可以使用,前提是大家需要提前安装好 JDK)

下面是tomcat安装教程的一篇文章:Tomcat8下载及安装配置教程(官网)-CSDN博客

解压好了我们就可以直接使用了,无需安装软件

启动tomcat服务器

那么怎么启动tomcat服务器呢?

进入bin目录,bin 目录下放的是 tomcat 的一些相关可执行脚本
.bat后缀的文件,是windows的批处理文件,.sh后缀的文件,是linux的shell脚本文件
双击startup.bat即可启动,你如果是linux,你就双击startup.sh

进入后,最后一行提示Server startup 就说明启动成功了

而对于上面的一堆看不懂的东西就是乱码

为什么会出现乱码呢?
Tomcat内部使用的编码方式是utf-8(我们当下最主流的编码方式)
但是我们的windows是"简体中文版",默认字符集是GBK,于是导致了cmd这个程序去跟随了系统的字符串。
数据是按照utf-8来构造的,但是cmd在显示时按照了GBK的方式来解析,这样就会出现乱码了。

那有没有办法让乱码消失?
有,但是风险很大,你可以改windows的注册表,但是如果一旦哪里改的有问题,你就等着重装系统。所以我这里非常不建议大家去修改。

另外,我们后续使用tomcat还有其他方式:
1.结合idea使用
2.在linux上使用
上面两种方法都是无乱码的,我们当前这点乱码无视即可。

当你启动服务器后,要想知道服务器是否真正启动运行?

你在网页中输入127.0.0.1:8080如果可以正常显示Tomcat的欢迎页面,那么就运行成功。

如果没显示就寄了

tomcat文件夹的各个文件作用

下面我们针对里面的重点文件讲述


bin 目录下放的是 tomcat 的一些相关可执行脚本,这个我们刚才知道了


conf 中放的是 tomcat 的配置文件,一个程序的功能是非常丰富的.就需要按需开启这里的某些功能.给程序猿使用的专业程序,一般很少会专门做一个界面,来让大家修改配置.毕竟程序猿是专业人士,咱们一般就都是通过配置文件的方式来进行设置的


lib,temp,work以及下面的多个小文件这里没什么用,我们不多说了


logs中放的就是日志(就是通过 System.out.println 等方式打印的一些字符串.),日志是调试一个服务器程序最重要的手段,后续自己写的程序,代码中打印的日志,就可以在上述目录中看到,
调试程序,不应该使用调试器嘛~~ 调试器,不适合给服务器程序使用,因为调试器要中断程序,而服务器是全程工作的。


webapps 里面放的是若干个webapp(网站),我们可以通过往这里面添加我们的代码从而完成自定义网站的部署和加载

进入ROOT目录

ROOT目录里面就可以放一些我们自己写的HTML

我们这里新建一个hello.html文件,然后用vscode进行编辑

我们原先输入127.0.0.1:8080可以进入Tomcat的欢迎页面

我们在这个基础上做一些改动,把它变成127.0.0.1:8080/hello.html按下回车
发现正好跳转到我们之前在ROOT下创建并编写的页面

那么这里有个问题,你直接点击该文件不也能打开那个页面吗?

需要注意的是:
前者通过tomcat访问,是可以让别人通过网络访问你的html的
后者是通过本地文件来访问,仅限于你自己主机访问

静态网页和动态网页

静态网页和动态页面有什么区别?

静态网页内容都是固定的,比如我们刚才在tomcat上部署的一个简单的html就是一个静态页面
而动态页面就是每次打开内容都是不固定的,比如b站不同的用户打开b站就是不同的感兴趣内容。此时动态页面就需要通过大量的代码,复杂的逻辑来实现。

而Tomcat 不仅可以支持静态页面,还能支持动态页面
**对于动态页面tomcat 提供了一组 api,可以让程序猿更方便的编写动态页面,称为 Servlet,**这就是下节课的内容了,它的内容比较多,需要很详细的讲述。

相关推荐
佩奇的技术笔记41 分钟前
Java学习手册:Web 应用架构概述
java
Miraitowa_cheems2 小时前
[Java EE] Spring 配置 和 日志
java·spring·java-ee
SuperherRo3 小时前
Web开发-JavaEE应用&原生和FastJson反序列化&URLDNS链&JDBC链&Gadget手搓
java·java-ee·jdbc·fastjson·反序列化·urldns
xxjiaz4 小时前
二分查找-LeetCode
java·数据结构·算法·leetcode
nofaluse5 小时前
JavaWeb开发——文件上传
java·spring boot
爱的叹息5 小时前
【java实现+4种变体完整例子】排序算法中【插入排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
java·算法·排序算法
爱的叹息6 小时前
【java实现+4种变体完整例子】排序算法中【快速排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格
java·算法·排序算法
6v6-博客6 小时前
2024年网站开发语言选择指南:PHP/Java/Node.js/Python如何选型?
java·开发语言·php
Miraitowa_cheems6 小时前
[Java EE] Spring AOP 和 事务
java·java-ee·aop·spring 事务
光头小小强0076 小时前
致远OA——自定义开发rest接口
java·经验分享·spring·tomcat