137.https是否能够发送http的请求

也许你也曾碰见这种问题,在一个https的网页里面,出于某些原因,想要发送http协议的请求.

一、问题的答案:https是否能够发送http请求

首先这种https混杂着http的情况叫做:混合内容.

  • 主动混合内容不可以(与页面交互的部分,下载的JS、iframe、样式表、flash和代码等,例如:用script标签引入http的js链接,script本身会加载链接的内容)
  • 被动混合内容可以(图片、视频、音频内容,例子:用img标签引入http的js链接,img本身是不可交互的,仅供展示)

未来随着浏览器的升级,可以预见被动混合内容也将不被允许发请求。因为这样是不安全的。
Chrome81,消灭混合内容,消灭https发http请求的情况

查阅书籍。
todo.

二、原因

原因显而易见,为了安全。

http为什么不安全
http为什么不安全?
现象:

  • 1、无限wifi攻击,http的传输是明文,截获了就什么都知道了
  • 2、垃圾广告攻击

原因:

  • 1、http的传输是明文,需要加密
  • 2、无法验证身份;只要请求正确,就给返回,返回的还是明文。给了中间人空间
  • 3、数据易篡改,因为传输要跳节点,某个节点可能被安插广告

继续查阅书籍。
todo.

三、案例(会Node可尝试,语言:Node.js,服务器框架:Express)

a.服务端和客户端各有一对公钥和私钥,使用公钥加密的数据只能用私钥解密,建立https传输之前,客户端和服务端互换公钥。

b.客户端发送数据前使用服务端公钥加密,服务端接收到数据后使用私钥解密,反之亦如此。

c.然后如果只是用 公钥 + 私钥,还会遇见一个中间人攻击的问题(简单点说,用户点进了骗子网站,比如一个仿淘宝的网站,就能很容易地获取到用户的淘宝账号、密码;现在的指纹登录从某种程度上也防止了这种攻击)。所以有一个签名证书,来确保服务端发给客户端的公钥是来自服务端,服务端可信任。

通过 a 和 b,解决了上面的http不安全的原因1-传输明文。
通过 c的认证,解决了上面的http不安全的原因2-中间人攻击,让钓鱼网站,模仿了真正的服务端也没用,它无法使用认证机构的私钥进行签名。(确保服务端正确)

3.1.让我们先开一个https的服务器

  • 3.1.1 安装openssl,然后进入安装目录下的bin目录

  • 3.1.2 使用openssl生成公钥和私钥

    // 生成服务器端私钥
    $ openssl genrsa -out server.key 1024 
    
    //生成服务端公钥
    $ openssl rsa -in server.key -pubout -out server.pem
    
  • 3.1.3 认证公钥

    //生成CA私钥
    $ openssl genrsa -out ca.key 1024
    //生成csr文件
    $ openssl req -new -key ca.key -out ca.csr
    //生成自签名证书
    $ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt
    //生成server.csr文件
    $ openssl req -new -key server.key -out server.csr
    //生成带有ca签名的证书
    $ openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt
    
  • 3.1.4 使用Express开启我们的https服务器

    const express = require('express')
    const fs = require('fs')
    const app = express()
    const https = require('https')
    // 对比普通的http
    const http = require('http')
    
    // 这里放https的配置文件,如果这里没有配置项的话,https页面会报:【此网页无法提供安全连接】
    const option = {
      // 公钥
      key: fs.readFileSync('./key/server.key'),
      // 证书
      cert: fs.readFileSync('./key/server.crt')
    }
    
    // 静态文件资源服务器,将网页挂在这里,然后用网页发起主动 http 请求、被动 http 请求
    // 这是为了方便我们测试的
    app.use(express.static('public'))
    
    app.get('/', (req, res, next) => {
      res.send('hello, world')
    })
    
    const httpsServer = https.createServer(option, app)
    const httpServer = http.createServer(option, app)
    
    httpsServer.listen(443)
    httpServer.listen(3000)
    

    然后我们创建一个 public 文件夹,在里面创建一个 test.html,之后分别打开我们的端口:
    A:https://localhost:443/test.html
    B:http://localhost:3000/test.html

    test.html内容

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
      <!-- jquery的https-cdn,是合法的请求 -->
      <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
      <!-- jquery的http -->
      <script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
    </head>
    <body>
    <header>我是hh.html</header>
    <img src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js" alt="">
    </body>
    </html>
    

3.2.我们主动、被动地发同一个http请求

地址:https://localhost:443/test.html
打开Chrome浏览器,输入地址,按F12,查看Network:

错误信息

Mixed Content: The page at 'https://localhost/test.html' was loaded over HTTPS, but requested an insecure script 'http://libs.baidu.com/jquery/2.1.1/jquery.min.js'. This request has been blocked; the content must be served over HTTPS.

完整截图:

从结果上看,https页面的Network只报了一个http请求错误。
从代码上看,我们两处使用了http的请求

3.3.总结答案

https通常无法发送http的请求。
会被浏览器阻止。
出于安全考虑。
图片的链接、视频的链接、音频的链接等被动请求是特殊情况。
未来也许连特殊情况也不会存在。


todo.

posted @ 2020-11-04 22:29  海客无心x  阅读(1343)  评论(0编辑  收藏  举报