跳到主要内容

使用Github Actions自动化部署博客

阅读需 16 分钟

image-20240402181234492

因为之前的博客太久没使用了就给关闭了,近来想重新开启遂决定重新部署一个,于是敲定了技术栈便开始动手,有兴趣的可以翻我之前的《如何利用Docusaurus打造个人站点,看这一篇文章就够了》文章

1.服务器搭建

首先你需要一台云服务器,这里的服务器可以从各大云服务厂商处购买不做赘述

1.1安装服务器操作面板

接下来就是安装操作系统和环境了,云服务器这块由于我不是十分了解linux,遂选择在linux的基础上安装宝塔面板进行服务器的管理,

1.2安装Web服务器

有了服务器之后,我们的项目部署到公网上,还需要有一个公网IP,以及一个Web服务器,比如Nginx、IIS、Apache等等

这里我们选择使用Nginx

2.配置自动化脚本部署

在这之前你需要了解CI/CD的一些相关知识

2.1选择 Github 项目仓库

这里以使用Github Actions为例

首先将本地代码推送到Github仓库,进入到仓库主页,点击顶部的Actions标签

image-20240402182010622

2.2新建工作流,配置 Actions

进入 Actions 后可以看到很多推荐的工作流模版,这里可以根据需要自行选择需要的模版,或者跳过模版,自行设置。

这里因为我是纯前端项目,所以我选择自定义。

image-20240402174454692

在这里面可以编写一些我们自定义的脚本

点击右上角的commit changes

会自动在项目 .github/workflows 目录下生成 main.yml 文件,我们可以把文件名字改成我们工作流的名称。当然,这里可以设置并存在很多工作流 yml 文件,例如 deploy.yml、test.yml、gh-page.yml 等。

这里分享一下我自己使用的部署脚本

# action名称
name: deploy-website

# 当代码合并到master分支的时候,执行下列脚本
on:
push:
branches: [master]
# 任务
jobs:
# docs-build为任务id可随意定义
docs-build:
runs-on: ubuntu-latest
steps:
- name: 切换到master分支拉取源码
uses: actions/checkout@master

- name: 安装指定版本的Node.js
uses: actions/setup-node@master
with:
node-version: "18.X"
# registry-url: https://registry.npmjs.org/ # 如果不配置将影响publish

- name: 安装依赖
run: npm install

- name: 构建dist
run: npm run build

- name: build 成功通知
run: echo npm 构建成功,请访问 http://8.134.54.104

- name: copy file via ssh password
uses: easingthemes/ssh-deploy@main
with:
# SSH私钥
SSH_PRIVATE_KEY: ${{ secrets.REMOTE_SSH_KEY }}
ARGS: "-rlgoDzvc -i"
# 构建产物的路径
SOURCE: "build/"
# 服务器ip
REMOTE_HOST: ${{ secrets.REMOTE_HOST_HK }}
# SSH用户账户
REMOTE_USER: ${{ secrets.REMOTE_USER }}
# 部署到到服务器地址
TARGET: '/www/server/nginx/html/blog'
EXCLUDE: "/build/, /node_modules/"
SCRIPT_BEFORE: |
whoami
ls -al
SCRIPT_AFTER: |
whoami
ls -al
echo $RSYNC_STDOUT

接着到setting下配置环境变量,因为例如像服务器ip密钥等这类敏感信息不宜直接明文展示,所以可以通过读取环境变量的方式来读取

2.3提交代码

提交代码触发自动化构建和部署

3.配置域名解析

到对应域名服务商下面

4.启用HTTPS

配置和应用SSL证书

关于https介绍

https协议是一种在客户端与服务端之间进行数据传输的协议 ,是为了解决HTTP协议的安全隐私问题做的一个补充, 可以对传输的数据进行加密保证通信的安全

全称叫做HTTP overSSL或者TLS,本质上使用HTTP协议进行通信,但是使用SSL或TLS对数据进行加密或验证(还可以验证服务器身份 )

解决了哪些问题

  • (防止被窃听) 传统的HTTP协议通信使用明文传输,内容可能会被窃听,有泄漏的风险

  • 防止中间人攻击)因为被窃听,不验证身份,双方都有可能遭遇伪装(中间人攻击)

  • (防止被篡改)无法验证报文的完整性,有可能已被篡改

  • (优化SEO)seo容易受损,不使用https,搜索引擎排名受影响,搜索引擎算法优先考虑加密的https网站,

SSL

secure socket layers (安全套接字层)

TLS

全称 transport layer security(传输层安全协议),是SSL的一个更新的版本

加密

哈希

从严格意义上来说,哈希算法并不属于加密算法,但它在信息安全领域起到了很重要的作用。

哈希算法能做什么用呢?其中一个重要的作用就是生成信息摘要,用以验证原信息的完整性和来源的可靠性。

支付宝怎么知道这个请求是真的来自该应用,并且没有被篡改呢?

请求的发送方把所有参数,外加双方约定的Key(例子中Key=abc)拼接起来,并利用哈希算法生成了一段信息摘要:

Hash(1234_100_abc) = 948569CD3466451F

而请求的接收方在接到参数和摘要之后,按照同样的规则,也把参数和Key拼接起来并生成摘要:

Hash(1234_100_abc) = 948569CD3466451F

如果最终发现两端信息摘要一致,证明信息没有被篡改,并且来源确实是该互联网应用。(只要参数修改了一点点,或者Key不一样,那么生成的信息摘要就会完全不同)

生成信息摘要的过程叫做签名,验证信息摘要的过程叫做验签

哈希算法包含哪些具体的算法呢?其中最著名的当属MD5算法。后来,人们觉得MD5算法生成的信息摘要太短(128位),不够安全,于是又有了SHA系列算法

但是哈希算法可以解决验签的问题,却无法解决明文加密的问题。这时候,就需要真正的加密算法出场了。

对称加密

通信双方约定好用同一种规则对数据进行加密和解密 ,缺点是如果被第三方破解了规则后,就可以读取数据并进行伪造

  1. 甲方选择某一种加密规则,对信息进行加密
  2. 乙方使用同一种规则,对信息进行解密

由于加密和解密使用同样规则(简称"密钥"),这被称为"对称加密算法",这种加密模式有一个最大弱点:甲方必须把加密规则告诉乙方,否则无法解密。保存和传递密钥,就成了最头疼的问题。

非对称加密

1976年,两位美国计算机学家Whitfield Diffie 和 Martin Hellman,提出了一种崭新构思,可以在不直接传递密钥的情况下,完成解密。这被称为"Diffie-Hellman密钥交换算法"。这个算法启发了其他科学家。人们认识到,加密和解密可以使用不同的规则,只要这两种规则之间存在某种对应关系即可,这样就避免了直接传递密钥。

这种新的加密模式被称为"非对称加密算法"。

  1. 乙方生成两把密钥(公钥和私钥)。公钥是公开的,任何人都可以获得,私钥则是保密的。
  2. 甲方获取乙方的公钥,然后用它对信息加密。
  3. 乙方得到加密后的信息,用私钥解密。

如果公钥加密的信息只有私钥解得开,那么只要私钥不泄漏,通信就是安全的。

如图所示,在非对称加密中存在一对密钥,其中一个叫做公钥,另一个叫做私钥。在加密解密的过程中,我们既可以使用公钥加密明文,使用私钥解密密文;也可以使用私钥加密明文,使用公钥解密密文。

这样设计有什么好处呢?看看通信的过程就知道了:

1.在双方建立通信的时候,服务端只要把公钥告诉给客户端,自己保留私钥。

2.客户端利用获得的公钥。加密另外一个密钥X(可以是对称加密的密钥),发送给服务端。

3.服务端获得消息后,用自己的私钥解密,得到里面隐含的密钥X。

4.从此以后,双方可以利用密钥X进行对称加密的通信了。

在这个过程中,即使公钥被第三方截获,甚至后续的所有通信都被截获,第三方也无法进行破解。因为第二步利用公钥加密的消息,只有私钥才能解开,所以第三方永远无法知道密钥X是什么。

在安全的拿到服务器的公钥之后,客户端会随机生成一个对称秘钥,使用服务器公钥加密,传输给服务端(服务端使用私钥解密,也就知道了这个对称密钥),此后,相关的 Application Data 就通过这个随机生成的对称秘钥进行加密/解密,服务器也通过该对称秘钥进行解密/加密:

举例来说就是客户端向服务端请求数据,服务端上有一个保险柜(公钥A)和一把钥匙(私钥B),服务端把保险柜(公钥A)发给客户端,客户端收到保险柜之后,将用来与服务端通信的另外一把保险柜钥匙C放在保险柜(公钥A)里面,保险柜只能使用私钥B打开,自然外界也就无法破解数据,所以说数据是安全的。SSL = 非对称加密+对称加密

身份验证

  1. 现在加密已经完成了,但还是无法确定通信的双方的真实身份,比如可能会有人利用相似的域名或者网站布局来进行伪造,好在https解决了这个问题 ,因为服务端需要申请SSL证书 ,来证明自己的身份 (SSL证书就是保存在源服务器的数据文件)

  2. 要让SSL证书生效,就要向CA颁发机构 (Certificate Authty)申请,这是一个受到信任的第三方机构,

  3. 证书除了表明域名的归属日期等信息外,证书里面还包含了特定的公钥和私钥,简单来说,服务器安装了证书之后 ,用户就可以通过https来进行访问了

浏览器再通过https进行访问,会依据TLS的版本会有不同的变化 ,这里以TLS1.2为例

首先正常的TCP三次握手不变

  • tcp三次握手以后,客户端发送了client hello给服务端,并告诉服务端支持TLS1.2版本和支持的加密套件

这里的加密套件可以理解为多种(此处为16种)不同的加密算法组合

  • 然后生成一个随机数发给服务端

  • 服务端收到客户端的消息,发送server hello给服务端 ,在响应报文里面会告诉客户端 ,服务端确认的支持的TLS版本以及选择的加密套件(选哪一种算法) ,并且也生成一个随机数发 给客户端

  • 服务端再发一个响应出示自己所持有的证书,这样浏览器件可以根据对照自己的证书信任列表来确认服务器是否可信

  • 紧接着服务器再把公钥发给客户端 (server key exchange ) ,(如果服务器也想要客户端的证书会在这里发出请求,比如登陆网银 )

  • 通知客户端通讯完成 ,发送server hello done

  • 截止到目前这些请求和响应依旧未进行加密

  • client key exchange现在轮到客户端来处理这些问题 ,客户端会生成第三个随机数 ,也叫预主密钥,用前面收到的来自服务端的公钥进行加密 ,并且把加密后的随机数 发送给服务端

  • 告诉服务器,往后的数据用商议好的加密套件(算法)和预主密钥来加密

  • 最后表示客户端TLS协商没有问题了,加密开始

  • 服务器表示准备好了 TLS握手成功 ,可以给数据加密然后交换了

http-7

证书的出现

非对称加密+对称加密也是有被挟持破解的风险的

中间人窃取到服务器发送客户端的公钥A+之后,给客户端返回自己的公钥B+,客户端拿到中间人的公钥B+对密钥X进行加密发送给中间人,中间人用私钥B-进行解密,也就破获了密钥X,再用窃取到的服务器的公钥A+对破解的客户端密钥X进行加密发送给服务器窃取数据;

为了解决这个问题,就用到了数字证书,那什么又是数字证书呢?

数字证书其实就是网站的身份证,由CA机构进行签发。

CA机构 。就是它会给网站颁发身份证。当某个网站想要启用HTTPS协议的时候,需要向CA机构申请一份证书,这个证书就是数字证书

数字证书包括了证书持有者信息、公钥和有效期等等信息。

有了这个证书之后,当浏览器向目标网站服务器发起请求时,服务器只需要把数字证书返回给浏览器就行了。因为是目标网站有数字证书,如同身份证一样,那浏览器就可以认为,返回数据给我的,就是这个网站。

这里又产生了一个问题,在证书本身传输的过程中,万一被中间人挟持并修改了咋办?

于是乎,数字签名登场了。说到签名,大家肯定都知道,签名嘛,在日常生活中,就是用一支笔,在一张纸上面进行签名。其实咱们的数字签名也是一样的。简单来说,我们可以理解为就是:CA机构在给网站颁发证书之前,在这份证书上面签个名。接下来我们来看看到底是如何签名的:

假设CA机构有一套非对称加密的 公钥A+私钥A-

1、网站向CA机构申请颁发数字证书;

2、CA机构通过审核之后,会生成一份证书数据(此时为明文,内容包括:证书持有者信息、网站公钥、和有效期等);

3、利用散列函数对证书的明文数据进行Hash处理,生成一份数据摘要

4、接着利用私钥A-对这份数据摘要进行加密,得到数字签名

5、将证书明文数据 + 数字签名 合并到一起,组成完整的数字证书;

5、将这份数字证书颁发给对应的网站。

这里需要注意的是,通常我们使用公钥加密,用私钥解密。而在数字签名中,我们使用私钥加密(相当于生成签名),公钥解密(相当于验证签名)。

利用散列函数对证书的明文数据进行Hash处理,生成一份数据摘要其实不是必须的,因为实际上,我们只需要对证书的明文数据进行签名就可以了,为什么这里我们还需要对明文数据先进行Hash处理呢?

这是因为,一般来说,一份证书的内容比较冗长,加之非对称加密也非常耗时,所以直接对原文签名,很耗时。其实CA机构签名的时候花的时间长也就罢了,但是在浏览器验证的时候,那就很痛苦了。这时候,我们就可以用散列函数对原数据进行Hash,得到短一些的数据摘要,然后再对数据摘要进行签名就可以了。

那么现在我们有了数字签名加持的数字证书,浏览器在接收到的时候,如何进行验证呢?

需要注意的是,我们的浏览器已经提前预存了CA机构的公钥,这把公钥的作用就是用来解锁数字签名的。

浏览器向目前网站服务器发起请求;

2、目标服务器把数字证书返回给浏览器(包括证书明文数据 + 数字签名);

3、浏览器拿到数字证书之后,先拿到签名,利用浏览器预存的CA机构的公钥,对签名进行解密,解密之后得到一份数据摘要(假设叫T),接着利用证书里面提供的Hash算法明文数据进行Hash,又得到一份数据摘要(假设叫S)。此时,如果 T=S ,那浏览器认为这份证书就是有效的,否则无效。

也许你还有疑问,为什么有了数字签名,就能校验数字证书是否被修改过呢? 我们来试一试吧:

1、浏览器向目前网站服务器发起请求;

2、目标服务器把数字证书返回给浏览器(包括证书明文数据 + 数字签名);

3、中间人挟持了数字证书,并修改了数字证书,接着他返回了修改之后的数字证书给浏览器;

4、浏览器开始验证,对证书数据(这份数据是被修改过的)进行hash,得到一份数据摘要,然后对数字签名用公钥解密之后也得到一份数据摘要,两份一对比,发现两份数据摘要对不上,显然是不安全的,于是停止了通信。

5.配置nginx

参考资料

Loading Comments...