-
Notifications
You must be signed in to change notification settings - Fork 0
/
local-search.xml
215 lines (102 loc) · 155 KB
/
local-search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>如何寄一封信?(中国国内)</title>
<link href="/2023/d25ec3c8f07b/"/>
<url>/2023/d25ec3c8f07b/</url>
<content type="html"><![CDATA[<p>很久没有更新了,想起我居然还有个 Blog 来着……</p><p>主要是最近没有遇到什么技术问题,本来准备重置一下 mirai 的部署教程但是 2.15 迟迟没有推出所以不好写,搁置下来了…所以绝对不是我想摸鱼,绝对不是(</p><p>因为没有遇到技术问题,也不好去写技术性的文章,所以随便写写,刚好昨儿跑了戳,写写怎么寄信,以后有人问我我就可以扔过去链接了(笑)。</p><p>这篇文章的篇幅可能略有点长,但是不要怕,寄信并不复杂,篇幅长只是因为本人的写作风格就是这样,喜欢把一句话能够给多数人讲明白的事拆成几句话来尽可能让剩下的少部分人也可以理解。</p><p>本文部分图片还没补上来,等找时间扫描补上。</p><p>入题前先说说为什么我喜欢寄信。</p><h2 id="1-为什么选择寄信?"><a href="#1-为什么选择寄信?" class="headerlink" title="-1. 为什么选择寄信?"></a>-1. 为什么选择寄信?</h2><p>在互联网如此发达的现在,我们可以使用 <code>SMS</code>、各类 <code>IM</code> 工具以及 <code>Email</code> 非常快捷的与别人联系。通常,这些工具只需要几秒就可以让你的信息递达对方。既然互联网如此方便,为什么还要选择寄信?</p><p>这个问题并没有一个统一的答案,但我给出的答案是这样的:</p><h3 id="1-1-法律保护"><a href="#1-1-法律保护" class="headerlink" title="-1.1 法律保护"></a>-1.1 法律保护</h3><p>宪法有这样的一条:</p><blockquote><p><em>《中华人民共和国宪法》 第四十条</em></p><p><strong>中华人民共和国公民的通信自由和通信秘密受法律的保护。</strong>除因国家安全或者追查刑事犯罪的需要,由公安机关或者检察机关依照法律规定的程序对通信进行检查外,任何组织或者个人不得以任何理由侵犯公民的通信自由和通信秘密。</p></blockquote><p>尽管使用电子方式通信也受保护,但这实际上很困难。互联网拉近了我们之间的距离,也将不法分子与我们之间的距离拉近。尽管使用了 HTTPS 等技术对通信进行了加密,但窃取通信事实上还是可能且时刻在发生的,如果不是专门做过防护的话是很难阻止的。且实施违法行为的个体很可能不位于中华人民共和国境内,所以很难对其进行打击。</p><p>而且,就算不被恶意窃取,你的通信内容也可能被服务提供商拿去进行分析以给你推送广告,或者用于训练模型。(注意是可能哦,没有针对任何厂商也没有贩卖焦虑的意思,这是一种可能性)</p><p>但是,寄信不一样。还是这一条:</p><blockquote><p><em>《中华人民共和国宪法》 第四十条</em></p><p>中华人民共和国公民的通信自由和通信秘密受法律的保护。<strong>除因国家安全或者追查刑事犯罪的需要,由公安机关或者检察机关依照法律规定的程序对通信进行检查外,任何组织或者个人不得以任何理由侵犯公民的通信自由和通信秘密。</strong></p></blockquote><p>这意味着什么呢?如果你选择寄信,<strong>只要你不是用于违法目的,这封信在送达至收件人手中前依法受保护,没有任何人有权打开它</strong>。也就是说,除了你和收件人没有任何人知道里面写了什么。除非它成为了无着邮件,无着邮件的介绍见后。就算是无着邮件,起拆也是一件非常严肃的事情,也不是可以随便处理的。</p><p>如何判断是不是违法目的呢?这个就不归邮政管了。之前听工作人员说过一例,一天从邮筒里开出来很多封信,远多于日常正常量,刚处理完有关部门就来了,现场开拆发现内件是某些喜欢在钱上印字的人的同类的学习资料……</p><p>总之,只要不瞎整,寄信就是最安全的通信方式之一。<span class="heimu" title="你知道的太多了">如果不考虑丢包率的话(</span><span class="heimu" title="你知道的太多了">当然随着信件普及条码之后丢包率已经很低了,只是开个玩笑</span></p><h3 id="1-2-见字如晤"><a href="#1-2-见字如晤" class="headerlink" title="-1.2 见字如晤"></a>-1.2 见字如晤</h3><p>比起看得见摸不着的电子信息,我认为以纸为载体看得见摸得着的纸质信件更能传递一些字面以外的信息。</p><p>例如,在互联网如此发达的现在,对方还愿意给你寄一封手写信,这是很难得的。</p><p>很早以前有这样一个说法,我觉得能很好的形容一封信与一条信息之间的差异:<strong>见字如晤</strong>。</p><h3 id="1-3-夹寄物品"><a href="#1-3-夹寄物品" class="headerlink" title="-1.3 夹寄物品"></a>-1.3 夹寄物品</h3><p>你可以在信件中夹寄一些非纸质物品,只要符合允许寄递的规定就可以,但原则上需要是挂号信,平信得看被不被发现。</p><p>这可以以很低的成本将物品寄达。(如果是平信真的低到离谱!)</p><p>好了,废话就到这里,下面正文。</p><h2 id="0-开始之前"><a href="#0-开始之前" class="headerlink" title="0. 开始之前"></a>0. 开始之前</h2><p>开始之前,我们需要准备一些必要的物品,包括:</p><ul><li>一支笔,钢笔或圆珠笔均可,能写就行,不要太粗(废话)</li><li>一个或一些邮政标准信封(可以在邮局获取)</li><li>一些信纸(是纸就行,但是建议是专门的信纸,通常克重更低,意味着可以用更少的邮资塞下更多张)</li><li>一些邮票(可以在邮局获取)</li></ul><p>以上是信函需要准备的,如果是明信片则只需要笔和明信片以及邮票,如果是邮资明信片则不需要贴票。非邮政发行的明信片,理论上可以交寄但需要看实际情况。</p><h3 id="0-1-信封的选择"><a href="#0-1-信封的选择" class="headerlink" title="0.1 信封的选择"></a>0.1 信封的选择</h3><p>为什么要教如何选择信封呢,因为寄信不是是个信封就行的。</p><h4 id="0-1-1-通常情况"><a href="#0-1-1-通常情况" class="headerlink" title="0.1.1 通常情况"></a>0.1.1 通常情况</h4><p>其实也没什么好说的,只要是邮政标准信封而不是花里胡哨的其他信封就行了。</p><p>原则上<strong>用于挂号信的信封必须是邮政标准信封</strong>,即背面可以找到 <code>印制单位、数量、出厂日期、监制单位和监制证号</code> 以及识别条码的符合国标 GB/T 1416 的信封。如果你不知道什么是挂号信,别急,后面会说。<strong>请注意区分信封的识别条码和邮件条码</strong>,不要混淆了,具体请往后看。</p><p>但是实际上,我咨询了多省多地多个支局的工作人员,均表示<strong>现在平信也需要使用邮政标准信封</strong>,且<strong>必须有识别条码</strong>,没有可能影响收寄。具体以你所在地情况为准。</p><p>一个符合上述标准的信封正反面如图所示:</p><p>图</p><p>图</p><p>你可以依据需求选择不同大小的信封,这个不影响寄递,但因为信封存在自重,所以不是越大越好。满足需求的前提下,信封面积越小越好。</p><p>另外一个注意的点,其实信封不是越厚实越好。尽管越厚实信件其中的内件就越可能被保护的更好,但是这是有代价的,就是重量。所以,只要符合国标的邮政标准信封,均可以用于寄信,不用特意选厚实的,只要符合国标你信件的内件就大概率不会在寄递过程中出现问题。</p><p>当然,这些规定并不是绝对的,存在例外。</p><h4 id="0-1-2-例外情况"><a href="#0-1-2-例外情况" class="headerlink" title="0.1.2 例外情况"></a>0.1.2 例外情况</h4><p>有一些特殊信封是不符合或不完全符合上述情况的,但可以正常寄递。</p><p>主要是下列几种:</p><ul><li>透明窗口信封(GB/T 22585)</li><li>机要信封(一般个人用不上,YZ/Z 0054.1)</li><li>国际商业回函信封(同样的个人用不上,找不到公开的统一标准,应该是定制的)</li><li>由中国邮政或中国集邮发行的邮资信封、首日封、纪念封(YZ/T 0088.1、YZ/T 0088.6)</li><li>邮政公事信封(大体上符合 GB/T 1416,通常加印“邮政公事”字样,寄件区印制单位信息。是邮政自己因公对内外发函专用的信封)</li><li>保价信封(保价函件的专用信封,YZ/T 0088.4)</li></ul><p>一般情况的通信除邮资信封、首日封、纪念封外,其他信封是很少见的,故不予说明。</p><p><strong>邮资信封、首日封、纪念封的使用除邮资外与普通信封完全一致</strong>,故下文不会区分。</p><h2 id="1-信息收集"><a href="#1-信息收集" class="headerlink" title="1. 信息收集"></a>1. 信息收集</h2><h3 id="1-1-收件人信息"><a href="#1-1-收件人信息" class="headerlink" title="1.1 收件人信息"></a>1.1 收件人信息</h3><p>想要寄出一封信或者一张明信片,我们显然需要知道一些收件人的基本信息以让邮政将信件送至收件人的手上。</p><p>这些基本信息包括:</p><ul><li>收件人姓名</li><li>收件人地址</li><li>收件人所在地邮政编码(可以在 <a href="https://dey.11185.cn/web/#/idtoolkitaddress">此处</a> 查询)</li><li>收件人电话(移动电话和固话均可)</li></ul><p>收件人地址需要注意,越详细越好,<strong>最好详细到门牌号</strong>,且<strong>千万不要出现冲突!</strong> </p><p>冲突示例:<strong>湖南</strong>省<strong>合肥</strong>市<strong>天安门广场</strong>(<strong>合肥</strong>在<strong>安徽</strong>,<strong>合肥</strong>和<strong>长沙</strong>并没有<strong>天安门广场</strong>,<strong>天安门广场</strong>在<strong>北京</strong>)</p><p>当你掌握收件人的以上信息时,只要正确并且挂号,这封信大概率可以好好的投递到收件人手上。</p><h3 id="1-2-寄件人信息"><a href="#1-2-寄件人信息" class="headerlink" title="1.2 寄件人信息"></a>1.2 寄件人信息</h3><p>你需要掌握你,也就是寄件人的一些基本信息,以供如果发生意外情况未能妥投时信件可以原路返回到你手上而不是被当作无着邮件处理。(无着邮件:既无法投递给收件人也无法退回给寄件人的邮件)</p><p>寄件人需要填写的信息与收件人需要填写的信息完全一致。通常是推荐填写,但是也可以不填,但需要自行承担丢失风险。</p><h3 id="1-3-邮局在哪里"><a href="#1-3-邮局在哪里" class="headerlink" title="1.3 邮局在哪里"></a>1.3 邮局在哪里</h3><p>你需要知道你所在地最近的邮局在哪里,以及收件人所在地最近的邮局在哪里,以便去交寄信件或询问情况。</p><p>使用各种电子地图查找即可,搜索 <code>邮局</code> 或者 <code>支局</code> 就可以找到,或者 <a href="https://dey.11185.cn/web/#/dotquery">此处</a> 查询(注意只勾选 <code>邮政网点</code> 和 <code>主题邮局</code> 进行查询)。</p><h2 id="2-信息填写"><a href="#2-信息填写" class="headerlink" title="2. 信息填写"></a>2. 信息填写</h2><h3 id="2-1-信封"><a href="#2-1-信封" class="headerlink" title="2.1 信封"></a>2.1 信封</h3><p>这是一个邮政标准信封(分区仅供参考,本人自己画的):</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx2023615213936.png" alt="邮政标准信封示例及分区"></p><p>现在,按照分区进行讲解。</p><h4 id="2-1-1-邮政编码区"><a href="#2-1-1-邮政编码区" class="headerlink" title="2.1.1 邮政编码区"></a>2.1.1 邮政编码区</h4><p>我们给定一个人进行举例,就叫他小王吧,小王住在 <code>湖南省长沙市岳麓区岳麓大道218号长沙市人民政府</code>,所在地邮政编码经查为 <code>410031</code>,手机号为 <code>1893244***2</code>(数据随意取的,理论上不与任何人关联,如有雷同纯属巧合)。后面的收址区也使用小王的信息进行举例。</p><p>在六个红框中填写收件人所在地的邮政编码,如下图所示:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx202361680802.png" alt="填写邮政编码"></p><h4 id="2-1-2-收址区"><a href="#2-1-2-收址区" class="headerlink" title="2.1.2 收址区"></a>2.1.2 收址区</h4><p>逐行填写收件人地址,格式如下:</p><ul><li>省、市、县(区)</li><li>详细地址</li><li>收件人姓名 (可选+称呼) 收</li><li>电话号码</li></ul><p>如图所示:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx202361681255.png" alt="收址填法示例1"></p><p>或者这样填(本人这么填):</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx202361681601.png" alt="收址填法示例2"></p><h4 id="2-1-3-寄址区"><a href="#2-1-3-寄址区" class="headerlink" title="2.1.3 寄址区"></a>2.1.3 寄址区</h4><p>同样给定一个人,叫他大王吧,大王住在 <code>福建省福州市鼓楼区乌山路96号福州市人民政府</code>,所在地邮政编码经查为 <code>350005</code>,手机号为 <code>18950259**7</code>(同样随意取,如有雷同纯属巧合)。</p><p>逐行填写寄件人地址,格式基本同收件人,建议名字后加写 <code>寄</code> 或在第一行加写 <code>From:</code> 等标识(此处使用第一种),如图所示:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx202361682029.png" alt="寄址填法示例"></p><p>当然不加写也是可以的,加写表达更清晰。</p><p>然后填写寄件人邮政编码,写在 <code>邮政编码</code> 四字后,如图所示:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx202361682322.png" alt="寄址邮政编码填法示例"></p><p>最后填写好的信封如图所示:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx2023616825.png" alt="填写好的信封示例"></p><h3 id="2-2-明信片"><a href="#2-2-明信片" class="headerlink" title="2.2 明信片"></a>2.2 明信片</h3><p>明信片与信封的填写方式基本一致,但收址建议使用第二个示例的写法,否则写不下。</p><p>填写好的明信片如下所示(这是邮资明信片,跟普通明信片理论上一致):</p><p>图</p><p>填写好信息后,就可以准备贴足邮票了。但贴邮票前,请注意先估算费用,避免超费被盖戳。</p><h2 id="3-资费估算"><a href="#3-资费估算" class="headerlink" title="3. 资费估算"></a>3. 资费估算</h2><p>信件和明信片的计费方式略有不同,故分开讲解。</p><h3 id="3-1-信件计费方式"><a href="#3-1-信件计费方式" class="headerlink" title="3.1 信件计费方式"></a>3.1 信件计费方式</h3><p>重量 20g 以内:</p><blockquote><p>本埠(即本县或本区,包括县级市)0.8元</p><p>外埠(除本埠外<strong>中国大陆地区任何一个地方</strong>)1.2元</p></blockquote><p>超重时,重量在 100g 以内,每 20g :</p><blockquote><p>本埠加收 0.8元</p><p>外埠加收1.2元</p><p>不满 20g 按 20g 计。</p></blockquote><p>例如,信件重量为<strong>15g</strong>时寄往外埠需要的资费=(1.2*1)=<strong>1.2元</strong>,重量为<strong>21g</strong>时寄往外埠需要的资费=(1.2*2)=<strong>2.4元</strong>,重量为<strong>30g</strong>时寄往外埠<strong>还是只需要2.4元</strong>,重量为<strong>50g</strong>时寄往外埠需要的资费=(1.2*3)=<strong>3.6元</strong>。</p><p>如果重量超过了 100g,100g 以上部分:</p><blockquote><p>每 100g 本埠加收1.2元</p><p>外埠加收2元</p><p>不满 100g 按 100g 计。</p></blockquote><p>例如,信件重量为<strong>101g</strong>时,寄往外埠需要的资费=100g以内资费+100g以外资费=(1.2*5)+(2*1)=<strong>8元</strong>。信件重量为<strong>201g</strong>时,寄往外埠需要的资费=(1.2*5)+(2*2)=<strong>10元</strong>。</p><p>挂号信函在上述计费的标准上加收挂号费3元。</p><p>保价信函在上述计费的标准上,先加收挂号费3元,保价额≤100元的加收保价费1元,保价额>100元的按保价额的1%加收保价费,不满100元的部分按100元收取。</p><p>邮资信封超重的,除去信封本身自带的资费后再加贴邮票。</p><h3 id="3-2-明信片计费方式"><a href="#3-2-明信片计费方式" class="headerlink" title="3.2 明信片计费方式"></a>3.2 明信片计费方式</h3><p>不分本外埠,中国大陆地区统一0.8元每张。</p><p>可以按挂号信函交寄,但会按信件标准计费。</p><p>可能可以按挂号印刷品交寄,我曾经就这么交寄过,但是挂号印刷品必须携带身份证交寄。<span class="heimu" title="你知道的太多了">当时给我交寄这个的工作人员可能不是很懂,第二次我又去的时候带着身份证去准备按挂刷交寄,另一个工作人员告诉我不用寄挂刷本来就可以且应该按挂号信函交寄,我说之前另一个人说一定要寄挂刷,他就跟我吐槽了那个人半天(</span></p><p>邮资明信片按挂号信函等交寄的,除去明信片本身自带的资费后再加贴邮票。</p><p>估算好资费之后,就可以按照资费粘贴邮票了。</p><h2 id="4-粘贴邮票"><a href="#4-粘贴邮票" class="headerlink" title="4. 粘贴邮票"></a>4. 粘贴邮票</h2><p>想要将信函或者明信片寄出去,需要粘贴足够面额的邮票。</p><p>邮票可以在邮局买到。如果你没有邮票,可以先看看怎么贴,然后带着胶棒去邮局买完直接贴好交寄。</p><p>邮票可以多贴但不能少贴,多出部分不找零不继承,作废。例如:如果你应付邮资是4.2元,你可以贴4张1.2元的邮票,这样总面额是4.8元,多出的0.6元等于送给邮政了,作废了。</p><p><strong>建议使用 PVA 固体胶棒(请勿使用 PVAL 等液体胶水)粘贴邮票!!</strong>(特别是普通邮票,不带背胶。纪念邮票和特种邮票基本都是带背胶的,可以使用清水粘贴,但需要练习。怕粘不好的话请用胶棒。)</p><p>当需贴的邮票只有一张时,粘贴在信封右上角的贴邮票处即可(小型张除外)。</p><p>粘贴时注意不要把胶抹到票面上即可。</p><p>如果需贴的邮票不止一张或者是小型张,先确保你选择的信封足够贴下邮票,然后从下列方案中选一个使用:</p><ul><li>如果空间足够,可以贴在贴邮票处旁,但请注意留下盖销间隙。如图所示:</li></ul><p><img src="//initialheart.oss.aunly.cn/img/nim/yzjx202361682849.png" alt="全部贴在正面示例,因为是扫描件所以做了技术处理"></p><p>注意如果寄挂号信尽量给条码留出空间,虽然空间不够时条码贴在正面的任何一个地方都可以,但是尽量不要让条码在非标准位置,避免给邮政的工作增加难度。</p><ul><li>在正面的贴邮票处贴一张邮票,其余邮票贴在信封的反面。如图所示:</li></ul><p>图</p><p>图</p><ul><li>全部的邮票全部贴在信封的反面,正面的贴邮票处不贴邮票。</li></ul><p>图</p><p>图</p><ul><li>使用较小的信封时,小型张应尽量贴在信封背面。</li></ul><h2 id="5-封口"><a href="#5-封口" class="headerlink" title="5. 封口"></a>5. 封口</h2><p>将内件放入信封,然后将信封右侧的封舌折好,压实排出封内空气后用胶水或胶棒粘好即可。</p><p>明信片就是一张卡片,不用封口。</p><h2 id="6-交寄邮件"><a href="#6-交寄邮件" class="headerlink" title="6.交寄邮件"></a>6.交寄邮件</h2><p>前往离你家最近的邮局柜台,咨询那里的工作人员交寄即可。</p><p>只要你按照上面的步骤完成了准备,交寄耗时通常不会超过 5min。</p><p>当然,如果你不准备用挂号信函等给据或需要当面交寄的业务,也可以将邮件投入邮局门口的邮筒。请注意,<strong>如果选择投筒,请一定要投入还在正常运营的邮局门口的邮筒!</strong>路边的邮筒有可能是已经不会开筒了作废了的邮筒。保险起见建议柜台交寄。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>填写好信息,贴足邮票,投进邮筒。</p><p>只需要三步就可以寄出一封信。寄信也没有想象中的难,对吗?</p><p>如果还有任何疑问,欢迎评论区留言。</p><p>Enjoy!</p>]]></content>
<categories>
<category>杂谈</category>
</categories>
</entry>
<entry>
<title>Nginx HTTP 基本身份验证(Basic Authentication) 配置记录</title>
<link href="/2023/524563b54490/"/>
<url>/2023/524563b54490/</url>
<content type="html"><![CDATA[<p>不久前,我在我的服务器上部署了一个 code-server 服务,为了进一步确保安全,我为站点配置了 HTTP 基本身份验证。本文记录过程及经验供以后自己或任何人参考。</p><h1 id="写在开始:环境要求"><a href="#写在开始:环境要求" class="headerlink" title="写在开始:环境要求"></a>写在开始:环境要求</h1><p>Nginx(废话)、最新的 OpenSSL(本文使用 OpenSSL 3.0.5 5 Jul 2022,也可采用其他方式得到密码摘要)。</p><h1 id="一、配置"><a href="#一、配置" class="headerlink" title="一、配置"></a>一、配置</h1><h2 id="1-生成密码摘要"><a href="#1-生成密码摘要" class="headerlink" title="1.生成密码摘要"></a>1.生成密码摘要</h2><p>经测试,服务器环境使用的 Nginx 1.20.2 无法使用 -6(SHA512)、-5(SHA256)等更安全的摘要算法。</p><p>可使用的最优的算法配置是 -apr1(Apache MD5)。</p><p>确保已正确配置 OpenSSL 的可执行程序,即在命令行下直接输入 <code>openssl</code> 可以输出帮助页。</p><p>使用如下指令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">openssl passwd -apr1 {% Password %}<br></code></pre></td></tr></table></figure><p>Example:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta prompt_">> </span><span class="language-bash">openssl passwd -apr1 123456</span> <br><span class="hljs-meta prompt_">$</span><span class="language-bash">apr1<span class="hljs-variable">$TVfJjT</span>/2<span class="hljs-variable">$Z6SDXixO4QTLt0SjZw3J40</span></span><br></code></pre></td></tr></table></figure><p>输出的 <code>$apr1$TVfJjT/2$Z6SDXixO4QTLt0SjZw3J40</code> 即为密码摘要串,其中:</p><p><code>$apr1</code> 表示算法,即 <code>apr1</code>;<code>$TVfJjT/2$Z6SDXixO4QTLt0SjZw3J40</code> 表示摘要内容,即 <code>TVfJjT/2$Z6SDXixO4QTLt0SjZw3J40</code>。</p><p>推荐密码使用 ASCII 字符。</p><h2 id="2-创建-auth-文件"><a href="#2-创建-auth-文件" class="headerlink" title="2.创建 auth 文件"></a>2.创建 auth 文件</h2><p>新建一个 <code>example.auth</code> 文件,其中 <code>example</code> 可改为任意 ASCII 内容。(为保证兼容性,理论上非 ASCII 也可以,扩展名理论上可以丢弃或改为其他)</p><p>假设你需要一个用户名为 <code>Example</code> 和一个用户名为 <code>example</code> 的用户,密码均为 <code>123456</code>,则填入以下内容:</p><figure class="highlight autoit"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs autoit">Example:$apr1$TVfJjT/<span class="hljs-number">2</span>$Z6SDXixO4QTLt0SjZw3J40<br>example:$apr1$TVfJjT/<span class="hljs-number">2</span>$Z6SDXixO4QTLt0SjZw3J40<br></code></pre></td></tr></table></figure><p>其中,<code>Example</code> 与 <code>example</code> 表示两个不同用户的用户名。<code>$apr1$TVfJjT/2$Z6SDXixO4QTLt0SjZw3J40</code> 表示该用户密码的摘要串。</p><p>可以在合理范围内任意添加用户,但最少必须有一个用户。用户名最好使用 ASCII 字符。</p><p>允许使用 <code>#</code> 或后跟一个 <code>:</code> 进行注释。</p><p>Example:</p><figure class="highlight elixir"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs elixir"><span class="hljs-comment"># Some Notes</span><br><span class="hljs-symbol">Example:</span><span class="hljs-variable">$apr1</span><span class="hljs-variable">$TVfJjT</span>/<span class="hljs-number">2</span><span class="hljs-variable">$Z6SDXixO4QTLt0SjZw3J40</span><span class="hljs-symbol">:This</span> is a example account.<br></code></pre></td></tr></table></figure><p>其中,<code>Some Notes</code>,<code>This is a example account.</code> 都被认为是注释,且不被 Nginx 识别。</p><h2 id="3-调整-Nginx-配置"><a href="#3-调整-Nginx-配置" class="headerlink" title="3.调整 Nginx 配置"></a>3.调整 Nginx 配置</h2><p>配置在 <code>http, server, location, limit_except</code> 中有效。</p><p>加入以下内容:</p><figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs django"><span class="language-xml">auth_basic </span><span class="hljs-template-tag">{% <span class="hljs-name">realm</span> %}</span><span class="language-xml"></span><br><span class="language-xml">auth_basic_user_file </span><span class="hljs-template-tag">{% <span class="hljs-name">Path</span> %}</span><br></code></pre></td></tr></table></figure><p>其中,<code>realm</code> 配置应显示给用户的提示信息,推荐使用单引号 <code>'</code> 或双引号 <code>"</code> 括住,但在内容中含有空格或其他易造成错误解析的内容时,必须使用单引号 <code>'</code> 或双引号 <code>"</code> 括住。<br><code>Path</code> 配置用户凭据文件(上文 auth 文件)的路径,可以使用相对路径或者绝对路径,但强烈推荐使用绝对路径,网络上的信息表明相对路径可能造成未知问题。但请注意,在 Windows 系统中,必须使用 <code>\\</code> 代替路径中的 <code>\</code> 以进行转义。推荐使用单引号 <code>'</code> 或双引号 <code>"</code> 括住,但在内容中含有空格或其他易造成错误解析的内容时,必须使用单引号 <code>'</code> 或双引号 <code>"</code> 括住。</p><p>Example:</p><figure class="highlight ada"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs ada">auth_basic <span class="hljs-symbol">'This</span> <span class="hljs-keyword">is</span> a example site.'<br>auth_basic_user_file <span class="hljs-symbol">'Z</span>:\Example\Example.auth'<br></code></pre></td></tr></table></figure><p>配置完成后,执行如下命令:</p><figure class="highlight ebnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs ebnf"><span class="hljs-attribute">nginx -s reload</span><br></code></pre></td></tr></table></figure><p>完成。</p><h1 id="二、Basic-验证的分析"><a href="#二、Basic-验证的分析" class="headerlink" title="二、Basic 验证的分析"></a>二、Basic 验证的分析</h1><p>Basic 验证的详细内容可以参阅 <a href="https://datatracker.ietf.org/doc/html/rfc7617">RFC 7617</a>。这里进行简单介绍。</p><p>对于一般的客户端,首先,客户端像往常的 HTTP(S) 请求一样向服务器发送请求。服务器将返回 <code>401(Unauthorized)</code> 状态码,并为返回附上 <code>WWW-Authenticate</code> 标头,其中包含了进行验证的方法(在这里是 <code>Basic</code>)及上文设置的 <code>realm</code>。此时,客户端将显示密码提示,在用户输入正确的用户凭据后,客户端通过在请求中附上 <code>Authorization</code> 标头进行验证。</p><p>(流程图,回头补上)</p><p>Basic 验证在 HTTP 环境下是<strong>不安全</strong>的。因为它使用明文传输用户凭据。因此,原则上,不应在未应用 HTTPS 或类似技术加密连接时使用 Basic 验证保护重要内容。尽管 RFC 7617 中说明 Basic 验证使用 base64 算法处理内容,但 base64 是可逆的,等同于明文传输。</p><p>尽管如此,Basic 验证仍有独属于它的优势:便携、易部署、兼容广。所以如果只是不希望让某些站点的内容被公开且公开也不会造成很大影响等不太重要的用途,可以使用 Basic 验证。</p><p>当然,实际上,无论何时,<strong>不推荐</strong>使用 Basic 验证保护重要内容,至少不要让它成为唯一的保护。</p><p>Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>code-server Windows 部署指南</title>
<link href="/2023/2b803cba7147/"/>
<url>/2023/2b803cba7147/</url>
<content type="html"><![CDATA[<p>很久没有更新了,刚好近期部署 code-server 遇到了一些问题,遂水一下。</p><p>不管你有没有这个问题:code-server 是什么?首先,介绍一下 code-server。</p><p>code-server,简而言之,一个在浏览器里的 VSCode,VSCode 能干啥它就能干啥。但是它还是与一般 VSCode 有很多不同,因为它可以操作位于部署该服务的服务器上的文件,甚至直接使用终端。对我来说,它最重要的两个用途是作为一个在浏览器中运行的终端和一个随时随地不管拿到什么设备有浏览器就能用且可以直接同步我的任何更改到所有需要的设备上的 IDE。</p><p>当然,这也解决了我的一个困扰:没法随时随地的方便快捷的编写博文。这是我近期没有更新的重要原因。这篇博文就是通过 code-server 编写的。</p><p>介绍到此为止,下面进入正题,开始部署。</p><h1 id="写在开始"><a href="#写在开始" class="headerlink" title="写在开始"></a>写在开始</h1><p>为什么要在官方已有文档的情况下编写这篇文章?请看 <a href="https://github.com/coder/code-server/issues/6045">这个 issue (#6045)</a>。<span class="heimu" title="你知道的太多了">绝对不是想水</span></p><p>然后就是本站 About 页所述了。官方文档毕竟英文,机翻不一定好理解。</p><h2 id="环境介绍"><a href="#环境介绍" class="headerlink" title="环境介绍"></a>环境介绍</h2><p>本文在 Windows 10 22H2 下编写并在 Windows Server 2022 数据中心版上测试通过,通常亦适用于 Windows 10 22H2 版本的近期版本及对等的 Windows Server 系统及其近期版本。</p><p>本文在 64 位操作系统环境下编写,这是现代计算机几乎必备的要素。如果你因还在使用 32 位设备而使用 32 位系统,建议你更新设备。</p><p>本文内容涉及程序使用编写时的最新版本,随着版本的更新,可能会有些许细节有些不同。(2023-3-4 UTC+8)</p><h1 id="一、Git-环境的准备"><a href="#一、Git-环境的准备" class="headerlink" title="一、Git 环境的准备"></a>一、Git 环境的准备</h1><p>由于安装过程需要执行 sh 脚本,综合考虑选择 Git Bash,为此需要安装 Git。</p><p>如果你已经有 Git,可以跳过本节。</p><h2 id="1-下载-Git"><a href="#1-下载-Git" class="headerlink" title="1.下载 Git"></a>1.下载 Git</h2><p><a href="https://git-scm.com/download/win">点击此处</a> 跳转至 Git 官网 Windows 版本下载页面。</p><p>如图所示:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/4.png" alt="Git 官网下载页面"></p><p>单击图中划线部分超链接,下载最新版本的 Git。</p><h2 id="2-安装-Git"><a href="#2-安装-Git" class="headerlink" title="2.安装 Git"></a>2.安装 Git</h2><p>打开下载的 exe 文件(可能出现 UAC,选择是即可),得到以下界面:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/git2023340041.png" alt="Git 安装向导界面"></p><p>一路同意协议下一步,如果你不清楚选项的用途,那么<strong>不要改变任何默认选项</strong>。</p><p>等待读条完成即可。</p><p>建议你重启一下设备,此时完成 Git 的安装。</p><h1 id="二、Node-js-环境的准备"><a href="#二、Node-js-环境的准备" class="headerlink" title="二、Node.js 环境的准备"></a>二、Node.js 环境的准备</h1><p>依照官方文档,在 Windows 下官方推荐通过 npm 方式部署 code-server。</p><p>npm,也就是 Node Package Manager,Node 包管理器,顾名思义,是 Node.js 的包管理器。</p><p>包管理器即软件包管理器是用来管理软件包的,就像是 Windows 控制面板中的 <code>程序</code>。你用 Node 的包管理器没有 Node 就好像是用 Windows 控制面板但没有 Windows,有什么意义?所以我们需要部署 Node.js。</p><p>如果你已经有 Node.js,那么你可以跳转至本节的第三小节。</p><h2 id="1-安装"><a href="#1-安装" class="headerlink" title="1.安装"></a>1.安装</h2><h3 id="1-1-下载-Node-js"><a href="#1-1-下载-Node-js" class="headerlink" title="1.1 下载 Node.js"></a>1.1 下载 Node.js</h3><p><a href="https://nodejs.org/download/release/v16.19.1/node-v16.19.1-x64.msi">点击此处</a> 跳转至 Node.js 官网 Node.js 16.19.1 Windows X64 版本安装包下载链接。</p><h3 id="1-2-安装-Node-js"><a href="#1-2-安装-Node-js" class="headerlink" title="1.2 安装 Node.js"></a>1.2 安装 Node.js</h3><p>打开下载的 msi 文件,得到以下界面:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/2.png" alt="Node.js 安装向导界面"></p><p>一路同意协议下一步,直到看到该界面:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/3.png" alt="Node.js 安装向导的核弹级选项"></p><p>通常情况下,除非你是全新环境,否则我建议你<strong>一定不要勾选图中所示的复选框</strong>,也就是图中所示的状态,点击下一步。<span class="heimu" title="你知道的太多了">当然就算你是全新环境我也不推荐你勾选它,这可能会把你的环境弄得一团糟还很难恢复</span></p><p>等待读条完成,中间可能出现 UAC,选择是即可。</p><p>建议你重启一下设备,此时完成 Node.js 的安装。</p><h2 id="2-配置"><a href="#2-配置" class="headerlink" title="2.配置"></a>2.配置</h2><h3 id="可选-2-1-更换-npm-镜像源"><a href="#可选-2-1-更换-npm-镜像源" class="headerlink" title="(可选)2.1 更换 npm 镜像源"></a>(可选)2.1 更换 npm 镜像源</h3><p>国内可能无法正常或以可接受的速度访问默认的 npm 源,所以我们可以选择更换 npm 镜像源。</p><p>此处以淘宝源为例,cmd 运行如下命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm config set registry https://registry.npm.taobao.org<br></code></pre></td></tr></table></figure><p>完成换源。</p><h3 id="2-2-更改-npm-默认使用的-Shell"><a href="#2-2-更改-npm-默认使用的-Shell" class="headerlink" title="2.2 更改 npm 默认使用的 Shell"></a>2.2 更改 npm 默认使用的 Shell</h3><p>在 Windows 中,npm 默认使用 CMD(Command Prompt, 命令提示符)作为 Shell 程序。</p><p>但,它并不支持执行 <code>.sh</code> 文件,所以不能使用它来安装 code-server。</p><p>那么怎么解决呢?答案是使用 Git Bash。假设你已经依照上文或自己完成了 Git 的安装,则可通过 cmd 运行如下命令更改 npm 默认使用的 Shell:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm config set script-shell "{% Program Path %}"<br></code></pre></td></tr></table></figure><p>其中,<code>{% Program Path %}</code> 是执行程序的路径。</p><p>假设你没有改变 Git 的安装路径,则你应该运行如下命令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm config set script-shell "C:\Program Files\Git\bin\bash.exe"<br></code></pre></td></tr></table></figure><p>运行后如未输出任何内容,则完成更改。</p><h1 id="三、code-server-的安装与配置"><a href="#三、code-server-的安装与配置" class="headerlink" title="三、code-server 的安装与配置"></a>三、code-server 的安装与配置</h1><p>现在我们完成了一切前置工序,是时候来安装 code-server 了。</p><h2 id="1-安装-1"><a href="#1-安装-1" class="headerlink" title="1.安装"></a>1.安装</h2><h3 id="可选-1-1-新建文件夹(?"><a href="#可选-1-1-新建文件夹(?" class="headerlink" title="(可选)1.1 新建文件夹(?"></a>(可选)1.1 新建文件夹(?</h3><span class="heimu" title="你知道的太多了">新建文件夹.jpg</span><p>找一个风水宝地,比如 <code>D:\</code>,创建一个文件夹。</p><p>本文设定此文件夹在 <code>D:</code> 下,名字是 <code>code-server</code>。你可以随意,但可能需要改动本文部分内容。</p><h3 id="1-2-npm-安装-code-server"><a href="#1-2-npm-安装-code-server" class="headerlink" title="1.2 npm 安装 code-server"></a>1.2 npm 安装 code-server</h3><p>cmd 切换工作路径至 <code>D:\code-server</code>,运行如下指令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install --global code-server --unsafe-perm<br></code></pre></td></tr></table></figure><p>等待读条完成,没有意外的报错的话完成安装。</p><h2 id="2-配置-1"><a href="#2-配置-1" class="headerlink" title="2.配置"></a>2.配置</h2><h3 id="2-1-初始化"><a href="#2-1-初始化" class="headerlink" title="2.1 初始化"></a>2.1 初始化</h3><p>运行如下指令以首次启动并初始化 code-server:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">code-server<br></code></pre></td></tr></table></figure><p>如果未能运行并得到 <code>'code-server' 不是内部或外部命令,也不是可运行的程序或批处理文件。</code> 错误,则换用如下指令:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npx code-server<br></code></pre></td></tr></table></figure><p>当显示 <code>info - Not serving HTTPS</code> 时,确保活动窗口是运行 code-server 的命令提示符,按 <code>Ctrl+C</code> 结束程序。</p><h3 id="2-2-调整配置文件"><a href="#2-2-调整配置文件" class="headerlink" title="2.2 调整配置文件"></a>2.2 调整配置文件</h3><p>打开 <code>C:\Users\{% User Name %}}\AppData\Roaming\code-server\Config\config.yaml</code>,可见以下内容:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">bind-addr:</span> <span class="hljs-number">127.0</span><span class="hljs-number">.0</span><span class="hljs-number">.1</span><span class="hljs-string">:8080</span><br><span class="hljs-attr">auth:</span> <span class="hljs-string">password</span><br><span class="hljs-attr">password:</span> {<span class="hljs-string">%</span> <span class="hljs-string">Password</span> <span class="hljs-string">%</span>}<br><span class="hljs-attr">cert:</span> <span class="hljs-literal">false</span><br></code></pre></td></tr></table></figure><p>可以更改其中 <code>bind-addr</code> 字段中的 <code>8080</code> 以改变服务运行的端口号。本文设定它为 <code>11451</code>。</p><p>务必更改 <code>password</code> 字段,这是登录 code-server 的密钥。这将是你登录 code-server 的唯一凭据,若是泄露则你的机器将面临极大风险,所以请尽量使用长且复杂的强口令。</p><p>最后,再次执行 <code>code-server</code> 命令,配置完成。</p><p>对了,还记得刚刚新建的 <code>code-server</code> 文件夹吗?你可以为上面的 <code>config.yaml</code> 创建一个快捷方式并放在里面方便访问。</p><p>还可以在里面新建一个 <code>code-server.cmd</code> 文件,内容是:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">code-server<br></code></pre></td></tr></table></figure><p>方便一键启动。</p><h1 id="强烈建议!!!-四、使用-Nginx-反向代理加密连接"><a href="#强烈建议!!!-四、使用-Nginx-反向代理加密连接" class="headerlink" title="(强烈建议!!!)四、使用 Nginx 反向代理加密连接"></a>(强烈建议!!!)四、使用 Nginx 反向代理加密连接</h1><p>上文提到,code-server 实际上就是一个运行在浏览器中的 VSCode。这意味着,一旦密钥被窃取,你机器的终端可以直接被操控。</p><p>所以,如果准备将 code-server 暴露至公网,则非常有必要为连接加密。如果不这么做,你的机器将面临极大风险。</p><p>若想了解更多信息,则可参考我的 <a href="https://www.initbili.top/2022/84452dac2fe6/">这篇文章</a>。</p><p>实际上,code-server 本身也支持 HTTPS,但不推荐你直接使用。没有原因。</p><p>另外,code-server 使用了 WebSocket 连接,这意味着需要一些小调整,调整后的配置如下:</p><figure class="highlight perl"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs perl"><span class="hljs-keyword">map</span> $http_upgrade $connection_upgrade {<br> default upgrade;<br> <span class="hljs-string">''</span> <span class="hljs-keyword">close</span>;<br>}<br>server {<br> <span class="hljs-keyword">listen</span> <span class="hljs-number">11451</span> ssl;<br> server_name example.com;<br><br> access_log logs/host.access.log main;<br><br> ssl_certificate example.com.pem;<br> ssl_certificate_key example.com.key;<br><br> location / {<br> add_header Content-Security-Policy upgrade-insecure-requests;<br> proxy_pass http:<span class="hljs-regexp">//</span><span class="hljs-number">127.0</span>.<span class="hljs-number">0</span>.<span class="hljs-number">1</span>:<span class="hljs-number">11451</span>/;<br> proxy_set_header Host $proxy_host;<br> proxy_read_timeout <span class="hljs-number">300</span>s;<br> proxy_send_timeout <span class="hljs-number">300</span>s;<br> proxy_set_header X-Real-IP $remote_addr;<br> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;<br> proxy_set_header Upgrade $http_upgrade;<br> proxy_set_header Connection $connection_upgrade;<br> }<br>}<br></code></pre></td></tr></table></figure><p>有关如何使用它,参考上方给出的文章连接。</p><h1 id="五、访问服务"><a href="#五、访问服务" class="headerlink" title="五、访问服务"></a>五、访问服务</h1><p>在部署的机器上访问 <code>127.0.0.1:11451</code> 即可。</p><p>如果需要暴露到公网,则请更改配置文件中 <code>bind-addr</code> 字段的 <code>127.0.0.1</code> 至 <code>0.0.0.0</code>。不推荐这样做,推荐使用 Nginx 反向代理暴露到公网。详见第四节。</p><h1 id="题外:Python-环境的准备"><a href="#题外:Python-环境的准备" class="headerlink" title="题外:Python 环境的准备"></a>题外:Python 环境的准备</h1><p>一开始我以为安装程序依赖 Python,所以需要配置 Python 环境,在测试本文流程时发现并不需要,但是写了还是留着备用。</p><p>这里使用 Python 3.8。</p><h2 id="1-下载-Python"><a href="#1-下载-Python" class="headerlink" title="1.下载 Python"></a>1.下载 Python</h2><p><a href="https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe">点击此处</a> 跳转至 Python 官网 Python 3.8.10 Windows X64 版本安装包下载链接。</p><h2 id="2-安装-Python"><a href="#2-安装-Python" class="headerlink" title="2.安装 Python"></a>2.安装 Python</h2><p>打开下载的 exe 文件,得到以下界面:</p><p><img src="//initialheart.oss.aunly.cn/img/nim/py202333461516.png" alt="Python 安装向导界面"></p><p>确保图中 ① 部分圈出的复选框被选中(打勾),然后单击图中 ② 部分圈出的选项。</p><p>等待读条完成,中间可能出现 UAC,选择是即可。</p><p>来到以下界面,单击图中圈出的选项,可能出现 UAC,选是即可。</p><p><img src="//initialheart.oss.aunly.cn/img/nim/py20233346116.png" alt="Python 安装向导完成界面"></p><p>建议你重启一下设备,此时完成 Python 的安装。</p><p>Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>Windows 批处理脚本在特定情况下的一个有趣现象</title>
<link href="/2023/3b05db071bc1/"/>
<url>/2023/3b05db071bc1/</url>
<content type="html"><![CDATA[<p>在文章的开头首先给各位拜个年,新年快乐!</p><p>不知道你会不会感到奇怪,为什么大过年的突然有了这篇文章呢?<span class="heimu" title="你知道的太多了">当然是因为上个月忘记水博文了这个月爬起来水一篇再说</span></p><p>事情的起因是这样的:我有一个定时执行某程序的需求,因为我的服务器是 Windows,所以我准备使用批处理来达成目的,于是:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs shell">:: 关闭回显<br>@echo off<br>:: 为死循环打一个开始标记<br>:loop<br>:: 执行目标程序<br>example<br>:: 利用 timeout 来获得足够的间隔<br>timeout -t {XXsec} -NOBREAK<br>:: 避免 timeout 可能的误差,让目标程序更晚执行<br>ping 127.0.0.1<br>:: 跳转到 loop 标记,开始死循环<br>goto loop<br></code></pre></td></tr></table></figure><p>我编写了以上代码,并保存为 <code>timeout.bat</code>,随后我执行它,奇怪的事情发生了:</p><figure class="highlight dust"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs dust"><span class="hljs-template-variable">{执行一次程序的输出}</span><span class="language-xml"></span><br><span class="language-xml"></span><span class="hljs-template-variable">{执行一次程序的输出}</span><span class="language-xml"></span><br><span class="language-xml"></span><span class="hljs-template-variable">{执行一次程序的输出}</span><span class="language-xml"></span><br><span class="language-xml">...</span><br></code></pre></td></tr></table></figure><p>我得到了以上的运行输出,而正确的输出应该为:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs routeros">{执行一次程序的输出}<br><br>等待 XX 秒,按 CTRL+C 退出 <span class="hljs-built_in">..</span>.<br><br>正在<span class="hljs-built_in"> Ping </span>127.0.0.1 具有 32 字节的数据:<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br><br>127.0.0.1 的<span class="hljs-built_in"> Ping </span>统计信息:<br> 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),<br>往返行程的估计时间(以毫秒为单位):<br> 最短 = 0ms,最长 = 0ms,平均 = 0ms<br>{执行一次程序的输出}<br><span class="hljs-built_in">..</span>.<br></code></pre></td></tr></table></figure><p>这么看,似乎延时以及之后的 Ping 并没有被执行,而是被“跳过”了,这令我十分不解,于是我陷入了思考……</p><p>突然我灵光一闪,似乎 <code>timeout</code> 既可以指代 Windows 环境变量下的 <code>timeout.exe</code>,也可以指代这个批处理 <code>timeout.bat</code>!</p><p>想通这一点后,我将批处理的文件名改为 <code>timegetout.bat</code> 并保存,于是它正常的运行了起来。</p><p>这便是一个很重要的特性:cmd 检索环境变量的优先级是要低于检索命令执行的目录的。</p><p>可以轻松的证明这一点:在 <code>C:\Windows</code> 下放入一个内容为 <code>echo printest</code> 的 <code>printest.bat</code>,并使用 Win + R 打开命令提示符输入 <code>printest</code> 并执行,可以得到以下日志:</p><figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs avrasm">Microsoft Windows [版本 <span class="hljs-number">10.0</span>.xxxxx.xxxx]<br>(c) Microsoft Corporation。保留所有权利。<br><br><span class="hljs-symbol">C:</span>\Users\Example>printest<br><span class="hljs-symbol">C:</span>\Users\Example>echo printest<br>printest<br><br><span class="hljs-symbol">C:</span>\Users\Example><br></code></pre></td></tr></table></figure><p>现在,我们在 <code>C:\Users\Example</code> 下放入一个内容为 <code>ping 127.0.0.1</code> 的 <code>printest.bat</code> 后重复上述步骤可以得到以下日志:</p><figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs routeros">Microsoft Windows [版本 10.0.xxxxx.xxxx]<br>(c) Microsoft Corporation。保留所有权利。<br><br>C:\Users\Example>printest<br>C:\Users\Example>ping 127.0.0.1<br>正在<span class="hljs-built_in"> Ping </span>127.0.0.1 具有 32 字节的数据:<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br>来自 127.0.0.1 的回复: 字节=32 时间<1ms <span class="hljs-attribute">TTL</span>=128<br><br>127.0.0.1 的<span class="hljs-built_in"> Ping </span>统计信息:<br> 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),<br>往返行程的估计时间(以毫秒为单位):<br> 最短 = 0ms,最长 = 0ms,平均 = 0ms<br><br>C:\Users\Example><br></code></pre></td></tr></table></figure><p>以上是对这个特性的介绍和证明。</p><p>那么它有什么用呢?这就留给大家探索了。</p><p>Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>记录</category>
</categories>
</entry>
<entry>
<title>Windows 系统下的高精度网络时间守时配置</title>
<link href="/2022/76edc2121eba/"/>
<url>/2022/76edc2121eba/</url>
<content type="html"><![CDATA[<p>现今计算机技术的飞速发展使其应用的更加广泛。在软件部分,Windows 操作系统可以说是一个典型范例,它的广泛应用助力计算机走进千家万户。Windows 默认配置的时间校准对于一般用户已经足够使用,但是在某些领域,Windows 默认的时间精确度不能满足需求。本文帮助您配置在 Windows 系统下基于 Windows 时间服务的高精度网络守时。</p><span id="more"></span><h2 id="开始之前"><a href="#开始之前" class="headerlink" title="开始之前"></a>开始之前</h2><p>在开始操作之前,我们需要明确一些注意事项。</p><div class="note note-warning"> <p><span style="color:#FF5B15"><strong>警示</strong></span><br>请注意,高精度的时间对于一般用户是不必要的。<br>这可能会导致耗能增加,我不推荐您在没有必要时为设备配置高精度的时间。尽管对于个人来说,这个改变可能是微小的,它可能无法给您造成超过几分钱的金钱负担,但若这一点一滴累积起来,产生的耗能会是巨大的。<br>举个例子,我们平常访问的互联网,它无时无刻都在消耗对个人来说是天文数字的能源且产生大量碳排放。您对本站的访问同样为这些耗能和碳排放做了“贡献”。我们可能无法做到完全不产生耗能和碳排放,但我想我们应该尽可能地降低它。<br><strong>个人的力量是微小的,但当点滴汇聚,终会汇为江河。</strong><br>另外,对于移动式设备,无论是否有高精度时间的需求都不推荐配置高精度的时间,除非您将其作为固定设备使用。因为这会影响续航。</p> </div><p>微软文档指出,<strong>Windows 10 1607 或 Windows Server 2016 1607 之前的版本</strong>上的 Windows 时间服务提供满足 Kerberos 5 身份验证要求所需的时间精度及为加入到公共 Active Directory 林的 Windows 客户端和服务器提供大致准确的时间。<strong>在前述操作系统中,更优的精度超出其 Windows 时间服务的设计规范。</strong>在 <strong>Windows 10 1607 或 Windows Server 2016 1607 及更新的版本</strong>上,符合条件时,Windows 时间服务可为设备提供<strong>最优</strong> <strong>1ms</strong> 的精度。</p><p>如果您的设备不在上述高精度时间支持系统的范围内,而您确有迫切需求,<strong>请考虑升级或更换设备。</strong></p><p>可以通过 <code>winver</code> 验证系统版本。Win + R 并输入 <code>winver</code> 回车,查看版本是否在 <strong>1607 或更高版本</strong>上,及内部版本号是否在 <strong>14393 及以上</strong>。</p><p><strong>如果您为整个系统配置高精度时间,全系统设备均需满足系统要求。</strong></p><p>本文默认您在<strong>中国大陆(不含港澳台)</strong>,且到中国科学院国家授时中心公共 NTP 服务器的<strong>网络连接良好</strong>,<strong>累计单向网络延时<100ms</strong>。这可以提供 1s 的精度。更优的精度需要您自行调整设置。如何调整及累计单向网络延时的计算参见 <a href="https://learn.microsoft.com/zh-cn/windows-server/networking/windows-time-service/support-boundary">Microsoft Learn</a>。</p><h2 id="自动配置"><a href="#自动配置" class="headerlink" title="自动配置"></a>自动配置</h2><p>笔者自己配置好后顺手写了一个小脚本,可以帮助你快速完成配置。</p><p>在 <a href="//a.1314.cool/HIPNTP.7z">这里</a> 下载。</p><p><strong>请注意,请确定添加注册表,否则配置无效。</strong></p><p>配置完成后你应该在验证页看到这样的提示:</p><p><img src="//initialheart.oss.aunly.cn/img/p4/img.png" alt="time.is 对时验证"></p><p>时差仅供参考,每次刷新基本都会变,重要的是提示是否对准。</p><h2 id="手动配置"><a href="#手动配置" class="headerlink" title="手动配置"></a>手动配置</h2><p><a href="https://learn.microsoft.com/zh-cn/windows-server/networking/windows-time-service/configuring-systems-for-high-accuracy">Microsoft Learn</a></p><h2 id="FAQ"><a href="#FAQ" class="headerlink" title="FAQ"></a>FAQ</h2><h3 id="time-is-提示未能对齐"><a href="#time-is-提示未能对齐" class="headerlink" title="time.is 提示未能对齐"></a>time.is 提示未能对齐</h3><p>检查到 ntp.ntsc.ac.cn 的网络连接后在管理员权限的命令提示符下运行:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">w32tm /resync<br></code></pre></td></tr></table></figure><p>通常可以解决问题。</p><p>如果网络连接不符合要求,那么未能对齐是正常的。请自行选用其他 NTP 后填入下面的命令并在管理员权限的命令提示符下运行以更改 NTP 服务器:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">w32tm /config /update /manualpeerlist:NTP地址<br></code></pre></td></tr></table></figure><h3 id="我想退回正常精度"><a href="#我想退回正常精度" class="headerlink" title="我想退回正常精度"></a>我想退回正常精度</h3><p>待我找到正常设备的配置后更新。</p><h3 id="为什么选用中国科学院国家授时中心的-NTP?阿里不是有提供时延普遍更优的-NTP-吗?"><a href="#为什么选用中国科学院国家授时中心的-NTP?阿里不是有提供时延普遍更优的-NTP-吗?" class="headerlink" title="为什么选用中国科学院国家授时中心的 NTP?阿里不是有提供时延普遍更优的 NTP 吗?"></a>为什么选用中国科学院国家授时中心的 NTP?阿里不是有提供时延普遍更优的 NTP 吗?</h3><p>个人喜好,可自行更改。同上方命令。</p><p>当然<strong>我推荐你别动</strong>。国家授时中心成立的时候马云还是个宝宝,阿里还不知道在哪呢。</p><p><strong>时延不是衡量 NTP 服务器的唯一标准,NTP 服务器自己有多准也十分重要。</strong></p><p>这是我个人的观点。</p><p>当然,不管用什么,总会比 time.windows.com 好。</p><p>Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>为你的 Hexo 定制标签语法!</title>
<link href="/2022/74cf12f2759b/"/>
<url>/2022/74cf12f2759b/</url>
<content type="html"><![CDATA[<p>不知道你是否有用过类似:</p><div class="note note-success"> <p>这样</p> </div><div class="note note-warning"> <p>这样</p> </div><div class="note note-danger"> <p>又或是这样的标签呢?</p> </div><p>以上标签写的时候长这样:</p><figure class="highlight django"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs django"><span class="hljs-template-tag">{% <span class="hljs-name">note</span> success %}</span><span class="language-xml"></span><br><span class="language-xml">这样</span><br><span class="language-xml"></span><span class="hljs-template-tag">{% <span class="hljs-name">endnote</span> %}</span><span class="language-xml"></span><br><span class="language-xml"></span><br><span class="language-xml"></span><span class="hljs-template-tag">{% <span class="hljs-name">note</span> warning %}</span><span class="language-xml"></span><br><span class="language-xml">这样</span><br><span class="language-xml"></span><span class="hljs-template-tag">{% <span class="hljs-name">endnote</span> %}</span><span class="language-xml"></span><br><span class="language-xml"></span><br><span class="language-xml"></span><span class="hljs-template-tag">{% <span class="hljs-name">note</span> danger %}</span><span class="language-xml"></span><br><span class="language-xml">又或是这样的标签呢?</span><br><span class="language-xml"></span><span class="hljs-template-tag">{% <span class="hljs-name">endnote</span> %}</span><br></code></pre></td></tr></table></figure><p>而部署出来就变成了这样:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"note note-success"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">p</span>></span>这样<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"note note-warning"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">p</span>></span>这样<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"note note-danger"</span>></span><br> <span class="hljs-tag"><<span class="hljs-name">p</span>></span>又或是这样的标签呢?<span class="hljs-tag"></<span class="hljs-name">p</span>></span><br> <span class="hljs-tag"></<span class="hljs-name">div</span>></span><br></code></pre></td></tr></table></figure><p>那么问题来了,这是怎么实现的?</p><h2 id="如何实现"><a href="#如何实现" class="headerlink" title="如何实现"></a>如何实现</h2><p>这使用了 Hexo 的一个扩展:标签(Tag)。</p><p>以上篇文章提到的萌娘百科黑幕为例,假设我想用一个标签语法来替代手动插入 HTML 的操作,以本站主题 Fluid 为例。</p><p>我们打开主题根目录,因为笔者使用 npm 安装,故主题根目录在 <code>node_modules\hexo-theme-fluid</code>。进入 <code>scripts\tags</code> 新建一个 <code>heimu.js</code>。</p><p>写入以下内容:</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">/* global hexo */</span><br><span class="hljs-meta"></span><br><span class="hljs-meta">'use strict'</span>;<br><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">heimu</span> = (<span class="hljs-params">args</span>) => {<br> args = args.<span class="hljs-title function_">join</span>(<span class="hljs-string">' '</span>).<span class="hljs-title function_">split</span>(<span class="hljs-string">'@'</span>);<br> <span class="hljs-keyword">const</span> title = args[<span class="hljs-number">0</span>] || <span class="hljs-string">'你知道的太多了'</span>;<br> <span class="hljs-keyword">const</span> text = args[<span class="hljs-number">1</span>] || <span class="hljs-string">''</span>;<br><br> !text && hexo.<span class="hljs-property">log</span>.<span class="hljs-title function_">warn</span>(<span class="hljs-string">'[Fluid] Heimu text must be defined!'</span>);<br><br> <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="heimu" title="<span class="hljs-subst">${title.trim()}</span>"><span class="hljs-subst">${text}</span></span>`</span>;<br>};<br><br><span class="hljs-comment">// {% heimu title @text %}</span><br>hexo.<span class="hljs-property">extend</span>.<span class="hljs-property">tag</span>.<span class="hljs-title function_">register</span>(<span class="hljs-string">'heimu'</span>, heimu, { <span class="hljs-attr">ends</span>: <span class="hljs-literal">false</span> });<br></code></pre></td></tr></table></figure><p>保存,在文章中写入:</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs text">{% heimu @内容 %}<br></code></pre></td></tr></table></figure><p>并执行 <code>hexo c&hexo s</code>,现在你可以在本地看到<span class="heimu" title="你知道的太多了">内容</span>这样的黑幕,而它的 HTML 长这样:</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"heimu"</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"你知道的太多了"</span>></span>内容<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br></code></pre></td></tr></table></figure><h2 id="解析"><a href="#解析" class="headerlink" title="解析"></a>解析</h2><p>解析实现可以分为两部分:JS 与 标签插件。</p><h3 id="JS"><a href="#JS" class="headerlink" title="JS"></a>JS</h3><p>刚刚的 JS 做了这样的事:</p><ul><li>声明该标签应/可传入的参数及默认值</li><li>当未传入 <code>text</code> 参数时向 log 输出一个 <code> WARN</code></li><li>定义替换该标签所在位置的 HTML</li><li>告诉 Hexo 使用标签插件</li></ul><p>这个 JS 十分简单,足够简明,故并不展开分点讲解。</p><p>事实上文件名可以由你自己任意指定,例如你可以写成 <code>muhei.js</code> <code>hm.js</code>,这没有任何影响,只要保证后缀为 <code>.js</code> 即可。</p><p>需要注意的是,如果你使用的是不同于本站的主题,不用担心,在 <code>主题根目录\scripts</code> 下边随便扔!扔在这个目录底下的 JS 都会被 Hexo 处理。</p><h3 id="标签插件"><a href="#标签插件" class="headerlink" title="标签插件"></a>标签插件</h3><p>上面的示例已经很好地展示了标签插件的用法。</p><p>除了上面示例的用法外,你是否注意到了 <code>ends: false</code>?</p><p>如果 <code>ends</code> 为 <code>true</code>,则标签需要有结束标签,例如:</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs text">{% heimu title %}<br>内容<br>{% endheimu %}<br></code></pre></td></tr></table></figure><p>另外,你还可以指定 <code>async</code> 选项,该选项为 <code>true</code> 时将启用非同步模式。</p><p>若有疑问可在评论区提出,Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>简单、快速地实现萌娘百科黑幕效果</title>
<link href="/2022/dba42bb67415/"/>
<url>/2022/dba42bb67415/</url>
<content type="html"><![CDATA[<p>相信很多站长朋友十分想在自己的网站上实现像萌百那样的<span class="heimu" title="你知道的太多了">黑幕效果(又称刮刮乐)</span>,我也一样,琢磨了一下之后在自己的站点成功的实现了,本文来教大家如何实现。</p><span id="more"></span><h2 id="实现"><a href="#实现" class="headerlink" title="实现"></a>实现</h2><p>将这段 CSS 添加至你的网站:</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><code class="hljs css"> <span class="hljs-comment">/* 萌娘百科 “黑幕” */</span><br> <span class="hljs-comment">/* 以下内容引用自萌娘百科 https://zh.moegirl.org.cn/MediaWiki:Gadget-site-styles.css,感谢! */</span><br> <span class="hljs-comment">/* MoeGirl Start */</span><br> <br><span class="hljs-selector-class">.heimu</span>,<br><span class="hljs-selector-class">.heimu</span> rt{<br> <span class="hljs-attribute">background-color</span>:<span class="hljs-number">#252525</span>;<br>}<br><br><span class="hljs-selector-class">.heimu</span>,<br><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span>,<br><span class="hljs-selector-tag">a</span> <span class="hljs-selector-class">.heimu</span>,<br><span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.new</span> <span class="hljs-selector-class">.heimu</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.new</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.external</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.external</span><span class="hljs-selector-pseudo">:visited</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.extiw</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.extiw</span><span class="hljs-selector-pseudo">:visited</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.mw-disambig</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.mw-redirect</span>{<br> <span class="hljs-attribute">transition</span>:color <span class="hljs-number">0.13s</span> linear;<br> <span class="hljs-attribute">color</span>:<span class="hljs-number">#252525</span>;<br> <span class="hljs-attribute">text-shadow</span>:none;<br>}<br> <br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span><span class="hljs-selector-pseudo">:hover</span>,<br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span><span class="hljs-selector-pseudo">:active</span>{<br> <span class="hljs-attribute">color</span>:white;<br>}<br> <br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">a</span>,<br><span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span>{<br> <span class="hljs-attribute">color</span>:lightblue;<br>}<br> <br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:visited</span>,<br><span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:visited</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span>{<br> <span class="hljs-attribute">color</span>:<span class="hljs-number">#C5CAE9</span>;<br>}<br> <br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.new</span>,<br><span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.new</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span>{<br> <span class="hljs-attribute">color</span>:<span class="hljs-number">#FCC</span>;<br>}<br> <br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.new</span><span class="hljs-selector-pseudo">:hover</span><span class="hljs-selector-pseudo">:visited</span>,<br><span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.new</span><span class="hljs-selector-pseudo">:hover</span><span class="hljs-selector-pseudo">:visited</span> <span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span>{<br> <span class="hljs-attribute">color</span>:<span class="hljs-number">#EF9A9A</span>;<br>}<br> <br><span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.extiw</span><span class="hljs-selector-pseudo">:visited</span>,<br><span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.extiw</span><span class="hljs-selector-pseudo">:visited</span><span class="hljs-selector-pseudo">:hover</span> <span class="hljs-selector-tag">span</span><span class="hljs-selector-class">.heimu</span>{<br> <span class="hljs-attribute">color</span>:<span class="hljs-number">#D1C4E9</span>;<br>}<br><br><span class="hljs-comment">/* MoeGirl End */</span><br></code></pre></td></tr></table></figure><p>对,就是这么的简单!</p><p>但请注意:<strong>不要删除注释中声明源自萌百及给出 URL 的部分!!!</strong></p><h2 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h2><p>相信很多站长看 CSS 便能看出如何使用它:</p><p>就是用一个 <code>class="heimu"</code> 的 span 标签包住内容即可。</p><p>你还可以通过 <code>title="悬停内容"</code> 定义鼠标悬浮在黑幕上时浮现的提示文字。</p><p>e.g.</p><span class="heimu" title="你知道的太多了">内容</span><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-tag"><<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"heimu"</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"你知道的太多了"</span>></span>内容<span class="hljs-tag"></<span class="hljs-name">span</span>></span><br></code></pre></td></tr></table></figure><h2 id="感谢"><a href="#感谢" class="headerlink" title="感谢"></a>感谢</h2><p>感谢萌娘百科允许使用这段 CSS!</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs css"><span class="hljs-comment">/* 以下注释节选自 https://github.com/MoegirlPediaInterfaceAdmins/MoegirlPediaInterfaceCodes/blob/master/src/gadgets/site-styles/MediaWiki:Gadget-site-styles.css commit 47c8f34。 */</span><br><br><span class="hljs-comment">/*</span><br><span class="hljs-comment"> * 请尊重萌娘百科版权,以下代码除非注明均是管理员手敲出来的!!!复制需要注明源自萌娘百科,并且附上URL地址 https://zh.moegirl.org.cn/MediaWiki:Gadget-site-styles.css</span><br><span class="hljs-comment"> * 版权协定:知识共享 署名-非商业性使用-相同方式共享 3.0</span><br><span class="hljs-comment"> */</span><br></code></pre></td></tr></table></figure><p>Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>Nginx 反向代理加密连接(HTTPS)简明教程</title>
<link href="/2022/84452dac2fe6/"/>
<url>/2022/84452dac2fe6/</url>
<content type="html"><![CDATA[<p>在信息安全形势愈发严峻的当下,通过传统的超文本传输协议(HTTP)传输的数据在代理提供者或发动攻击的不法分子眼中如同裸奔。因此,使用合适的措施加密用户与服务器之间的通信是十分之重要的。本文介绍通过 Nginx 快速的将传统超文本传输协议升级为超文本传输安全(HTTPS)协议的方法和要点。</p><span id="more"></span><h1 id="一、概述"><a href="#一、概述" class="headerlink" title="一、概述"></a>一、概述</h1><p>在本文开头,我们提到,通过 HTTP 传输的数据十分的不安全,在一般数据的传输中,这尚无大碍,但在涉及到用户的重要数据(如账号密码或隐私数据)时,这是十分危险的,所以我们需要通过对连接进行加密来保障信息在传输过程中的安全。</p><p>那么,什么是 HTTP,HTTPS 又是什么,为什么 HTTP 不安全?</p><h2 id="1-HTTP-S-是什么?"><a href="#1-HTTP-S-是什么?" class="headerlink" title="1.HTTP(S) 是什么?"></a>1.HTTP(S) 是什么?</h2><p>关于这一部分的内容,尽管我很想用我自己的话来展开讲以求能让你更好地理解它们,但菜鸟教程已有对这些问题的讲解,且大多足够详细易懂,所以如果你感兴趣,请参阅以下链接:</p><p><a href="https://www.runoob.com/http/http-intro.html">https://www.runoob.com/http/http-intro.html</a></p><p><a href="https://www.runoob.com/w3cnote/http-vs-https.html">https://www.runoob.com/w3cnote/http-vs-https.html</a></p><h2 id="2-为什么-HTTP-不安全?"><a href="#2-为什么-HTTP-不安全?" class="headerlink" title="2.为什么 HTTP 不安全?"></a>2.为什么 HTTP 不安全?</h2><p>首先,这是一般情况下正常的 HTTP 通讯简图:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img.png" alt="正常的 HTTP 通讯"></p><p>但是,如果你的域名服务器(DNS)不可信或被污染又或是其他情况例如代理提供商篡改了返回并抢先一步将篡改的返回包送达用户等实际上让访问得到的内容不是或不完全是域名所有者期望用户看到的内容的情况,我们将其称为劫持。</p><p>其中,由于域名服务器出现问题造成用户实际访问的服务器不是域名所有者所期望用户访问的服务器的情况,称作 DNS 劫持。</p><p>在信息传输过程中信息被篡改,导致用户或服务器得到的信息不是所期望的或符合设定的情况,称作 HTTP 劫持。</p><p>对于 DNS 劫持,HTTPS 并不能很好地防范,而是应该通过 DNSSEC 进行防范。</p><p>对于 HTTP 劫持,HTTPS 可以有效地解决这个问题。</p><p>这到底有多么重要呢?举个例子。你正在使用的网上银行网站使用 HTTP 而不是安全的 HTTPS,这个时候隔壁的张三恰巧知道你使用的网上银行网站不安全,便动起了歪心思,打开光纤箱把你家的光纤拉到了他的特制设备上,再由特制设备接着走正常的传输过程。这时你打开网上银行,张三马上收到了消息,当你在转账时,张三把对方的账号篡改为了自己的账号,并把转账金额篡改为余额,得手后立刻逃到了致远星。现在你只能看着余额页面大大的 0 抱头痛哭了。</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_1.png" alt="被劫持的通讯"></p><p>张三甚至还可以做得更隐蔽些:因为 HTTP 通过明文传输数据,所以可以通过监听知道你的密码,等你睡着了张三再与银行通讯刷走你的钱然后跑路。</p><p>事实上,类似这样的劫持可以在信息传输的任意阶段发生,在信息送达之前,你的信息只有天知道安不安全。</p><p>当然,不用担心这个例子真的在现实中发生,因为网银在传输这些信息时是 100% 使用 HTTPS 的,而且银行也采用了很多其他手段保护你的交易。但是这足以说明 HTTP 的不安全。</p><p>好了,我们进入正题。接下来我们讲解反向代理。</p><h1 id="二、反向代理的基本概念"><a href="#二、反向代理的基本概念" class="headerlink" title="二、反向代理的基本概念"></a>二、反向代理的基本概念</h1><p>在讲解反向代理前,我们应该讲解一下代理是什么。</p><h2 id="1-代理是什么?"><a href="#1-代理是什么?" class="headerlink" title="1.代理是什么?"></a>1.代理是什么?</h2><p>代理服务器,顾名思义,就是专门用来“代理”的服务器,那么它“代理”什么呢?自然是网络请求。</p><p>代理服务器的工作流程大致是:你的电脑告诉代理你要访问什么,代理替你访问,然后代理告诉你访问的结果。</p><p>这有什么作用呢?作用有很多,举一个重要用途的例子:你无法访问一个网站,但你可以访问代理服务器,而且代理服务器可以访问这个网站,此时你可以通过代理服务器访问这个网站。</p><h2 id="2-反向代理是什么?"><a href="#2-反向代理是什么?" class="headerlink" title="2.反向代理是什么?"></a>2.反向代理是什么?</h2><p>那么,反向代理又是什么呢?</p><p>通过上面的讲解,我们知道,代理是你,也就是用户访问目标用的,而反向代理,自然便是反过来,是访问目标所使用的代理。</p><p>一般的代理服务器是这样的:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_2.png" alt="正向代理工作流程"></p><p>而反向代理是这样的:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_3.png" alt="反向代理工作流程"></p><p>对于用户来说,反向代理服务器就是用户的目标,但反向代理服务器本身并不会处理用户的具体请求,只是将请求转给真正的目标。</p><p>那么,这又有什么用呢?作用同样有很多,比如本文的主题:加密传输。还有负载均衡,加响应头……等等功能。</p><p>接下来说明一下反向代理如何加密我们的连接。</p><h2 id="3-反向代理如何加密我们的连接?"><a href="#3-反向代理如何加密我们的连接?" class="headerlink" title="3.反向代理如何加密我们的连接?"></a>3.反向代理如何加密我们的连接?</h2><p>如下图:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_4.png" alt="反向代理加密原理"></p><p>你可能要问了:这不还是用了 HTTP 协议传输信息嘛!怎么就安全了呢?</p><p>此言差矣!前面我们提到:</p><blockquote><p>劫持可以在信息传输的任意阶段发生</p></blockquote><p>而通过反向代理,我们把可能可以有效劫持的区域缩小到了一个机房,甚至是一台机器内部。显然的,你要是连机房都看不好你搞个屁安全?人都进到你机房了还用劫持?所以这样便有效地保证了信息在传输过程中的安全。</p><p>现在我们知道了反向代理是什么,它如何保障我们的信息安全。接下来我们来实践一下,搭建一个反向代理来加密连接。</p><h1 id="三、Nginx-的配置"><a href="#三、Nginx-的配置" class="headerlink" title="三、Nginx 的配置"></a>三、Nginx 的配置</h1><p>要使用反向代理来加密连接,我们显然需要先搭建反向代理服务器。反向代理服务器有很多,本文主要说明 Nginx 的使用。</p><h2 id="1-搭建-Nginx-环境"><a href="#1-搭建-Nginx-环境" class="headerlink" title="1.搭建 Nginx 环境"></a>1.搭建 Nginx 环境</h2><p>笔者在 Windows 环境下编写本文,如果你使用其它系统,推荐你自行搜索这部分的内容,网络上已经有很多足够简明的教程且你使用的系统并不影响接下来介绍的大多数操作。</p><p>首先,访问 Nginx 官网的 <a href="https://nginx.org/en/download.html">下载页面</a>:</p><p>下载 <code>Stable version</code> 下的版本。</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_5.png" alt="Nginx 官网下载页面"></p><p>下载完成后,解压压缩包至一个合适的目录,你将得到这样的目录结构:</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs text">注:已删去版本号<br><br>nginx<br>├─ conf<br>│ ├─ fastcgi.conf<br>│ ├─ fastcgi_params<br>│ ├─ koi-utf<br>│ ├─ koi-win<br>│ ├─ mime.types<br>│ ├─ nginx.conf<br>│ ├─ scgi_params<br>│ ├─ uwsgi_params<br>│ └─ win-utf<br>├─ contrib<br>│ ├─ README<br>│ ├─ geo2nginx.pl<br>│ ├─ unicode2nginx<br>│ │ ├─ koi-utf<br>│ │ ├─ unicode-to-nginx.pl<br>│ │ └─ win-utf<br>│ └─ vim<br>│ ├─ ftdetect<br>│ ├─ ftplugin<br>│ ├─ indent<br>│ └─ syntax<br>├─ docs<br>│ ├─ CHANGES<br>│ ├─ CHANGES.ru<br>│ ├─ LICENSE<br>│ ├─ OpenSSL.LICENSE<br>│ ├─ PCRE.LICENCE<br>│ ├─ README<br>│ └─ zlib.LICENSE<br>├─ html<br>│ ├─ 50x.html<br>│ └─ index.html<br>├─ logs<br>├─ nginx.exe<br>└─ temp<br></code></pre></td></tr></table></figure><p>略去我们不会用到的部分,简化的目录结构如下:</p><figure class="highlight text"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs text">nginx<br>├─ conf<br>│ └─ nginx.conf<br>└─ nginx.exe<br></code></pre></td></tr></table></figure><p>不在简化的目录结构中的文件,你不用理会,也最好别动。</p><p>记住你解压 Nginx 的目录,现在你就搭建好了 Nginx 环境。没错!就是这么简单,开箱即用!</p><h2 id="2-配置-Nginx"><a href="#2-配置-Nginx" class="headerlink" title="2.配置 Nginx"></a>2.配置 Nginx</h2><p>现在,我们打开 <code>conf\nginx.conf</code>,你会看到以下内容:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-comment">#user nobody;</span><br><span class="hljs-attribute">worker_processes</span> <span class="hljs-number">1</span>;<br><br><span class="hljs-comment">#error_log logs/error.log;</span><br><span class="hljs-comment">#error_log logs/error.log notice;</span><br><span class="hljs-comment">#error_log logs/error.log info;</span><br><br><span class="hljs-comment">#pid logs/nginx.pid;</span><br><br><br><span class="hljs-section">events</span> {<br> <span class="hljs-attribute">worker_connections</span> <span class="hljs-number">1024</span>;<br>}<br><br><br><span class="hljs-section">http</span> {<br> <span class="hljs-attribute">include</span> mime.types;<br> <span class="hljs-attribute">default_type</span> application/octet-stream;<br><br> <span class="hljs-comment">#log_format main '$remote_addr - $remote_user [$time_local] "$request" '</span><br> <span class="hljs-comment"># '$status $body_bytes_sent "$http_referer" '</span><br> <span class="hljs-comment"># '"$http_user_agent" "$http_x_forwarded_for"';</span><br><br> <span class="hljs-comment">#access_log logs/access.log main;</span><br><br> <span class="hljs-attribute">sendfile</span> <span class="hljs-literal">on</span>;<br> <span class="hljs-comment">#tcp_nopush on;</span><br><br> <span class="hljs-comment">#keepalive_timeout 0;</span><br> <span class="hljs-attribute">keepalive_timeout</span> <span class="hljs-number">65</span>;<br><br> <span class="hljs-comment">#gzip on;</span><br><br> <span class="hljs-section">server</span> {<br> <span class="hljs-attribute">listen</span> <span class="hljs-number">80</span>;<br> <span class="hljs-attribute">server_name</span> localhost;<br><br> <span class="hljs-comment">#charset koi8-r;</span><br><br> <span class="hljs-comment">#access_log logs/host.access.log main;</span><br><br> <span class="hljs-section">location</span> / {<br> <span class="hljs-attribute">root</span> html;<br> <span class="hljs-attribute">index</span> index.html index.htm;<br> }<br><br> <span class="hljs-comment">#error_page 404 /404.html;</span><br><br> <span class="hljs-comment"># redirect server error pages to the static page /50x.html</span><br> <span class="hljs-comment">#</span><br> <span class="hljs-attribute">error_page</span> <span class="hljs-number">500</span> <span class="hljs-number">502</span> <span class="hljs-number">503</span> <span class="hljs-number">504</span> /50x.html;<br> <span class="hljs-section">location</span> = /50x.html {<br> <span class="hljs-attribute">root</span> html;<br> }<br><br> <span class="hljs-comment"># proxy the PHP scripts to Apache listening on 127.0.0.1:80</span><br> <span class="hljs-comment">#</span><br> <span class="hljs-comment">#location ~ \.php$ {</span><br> <span class="hljs-comment"># proxy_pass http://127.0.0.1;</span><br> <span class="hljs-comment">#}</span><br><br> <span class="hljs-comment"># pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000</span><br> <span class="hljs-comment">#</span><br> <span class="hljs-comment">#location ~ \.php$ {</span><br> <span class="hljs-comment"># root html;</span><br> <span class="hljs-comment"># fastcgi_pass 127.0.0.1:9000;</span><br> <span class="hljs-comment"># fastcgi_index index.php;</span><br> <span class="hljs-comment"># fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;</span><br> <span class="hljs-comment"># include fastcgi_params;</span><br> <span class="hljs-comment">#}</span><br><br> <span class="hljs-comment"># deny access to .htaccess files, if Apache's document root</span><br> <span class="hljs-comment"># concurs with nginx's one</span><br> <span class="hljs-comment">#</span><br> <span class="hljs-comment">#location ~ /\.ht {</span><br> <span class="hljs-comment"># deny all;</span><br> <span class="hljs-comment">#}</span><br> }<br><br><br> <span class="hljs-comment"># another virtual host using mix of IP-, name-, and port-based configuration</span><br> <span class="hljs-comment">#</span><br> <span class="hljs-comment">#server {</span><br> <span class="hljs-comment"># listen 8000;</span><br> <span class="hljs-comment"># listen somename:8080;</span><br> <span class="hljs-comment"># server_name somename alias another.alias;</span><br><br> <span class="hljs-comment"># location / {</span><br> <span class="hljs-comment"># root html;</span><br> <span class="hljs-comment"># index index.html index.htm;</span><br> <span class="hljs-comment"># }</span><br> <span class="hljs-comment">#}</span><br><br><br> <span class="hljs-comment"># HTTPS server</span><br> <span class="hljs-comment">#</span><br> <span class="hljs-comment">#server {</span><br> <span class="hljs-comment"># listen 443 ssl;</span><br> <span class="hljs-comment"># server_name localhost;</span><br><br> <span class="hljs-comment"># ssl_certificate cert.pem;</span><br> <span class="hljs-comment"># ssl_certificate_key cert.key;</span><br><br> <span class="hljs-comment"># ssl_session_cache shared:SSL:1m;</span><br> <span class="hljs-comment"># ssl_session_timeout 5m;</span><br><br> <span class="hljs-comment"># ssl_ciphers HIGH:!aNULL:!MD5;</span><br> <span class="hljs-comment"># ssl_prefer_server_ciphers on;</span><br><br> <span class="hljs-comment"># location / {</span><br> <span class="hljs-comment"># root html;</span><br> <span class="hljs-comment"># index index.html index.htm;</span><br> <span class="hljs-comment"># }</span><br> <span class="hljs-comment">#}</span><br><br>}<br></code></pre></td></tr></table></figure><p>复制下面这个推荐配置,替换掉里面的内容:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><br><span class="hljs-attribute">worker_processes</span> <span class="hljs-number">1</span>;<br><br><span class="hljs-section">events</span> {<br> <span class="hljs-attribute">worker_connections</span> <span class="hljs-number">1024</span>;<br>}<br><br><span class="hljs-section">http</span> {<br> <span class="hljs-attribute">include</span> mime.types;<br> <span class="hljs-attribute">default_type</span> application/octet-stream;<br><br> <span class="hljs-attribute">log_format</span> main <span class="hljs-string">'<span class="hljs-variable">$remote_addr</span> - <span class="hljs-variable">$remote_user</span> [<span class="hljs-variable">$time_local</span>] "<span class="hljs-variable">$request</span>" '</span><br> <span class="hljs-string">'<span class="hljs-variable">$status</span> <span class="hljs-variable">$body_bytes_sent</span> "<span class="hljs-variable">$http_referer</span>" '</span><br> <span class="hljs-string">'"<span class="hljs-variable">$http_user_agent</span>" "<span class="hljs-variable">$http_x_forwarded_for</span>"'</span>;<br><br> <span class="hljs-attribute">access_log</span> logs/access.log main;<br><br> <span class="hljs-attribute">sendfile</span> <span class="hljs-literal">on</span>;<br><br> <span class="hljs-attribute">keepalive_timeout</span> <span class="hljs-number">65</span>;<br><br> <span class="hljs-attribute">gzip</span> <span class="hljs-literal">on</span>;<br><br> <span class="hljs-comment">#server {</span><br> <span class="hljs-comment"># listen 443 ssl;</span><br> <span class="hljs-comment"># server_name localhost;</span><br><br> <span class="hljs-comment"># ssl_certificate cert.pem;</span><br> <span class="hljs-comment"># ssl_certificate_key cert.key;</span><br><br> <span class="hljs-comment"># ssl_session_cache shared:SSL:1m;</span><br> <span class="hljs-comment"># ssl_session_timeout 5m;</span><br><br> <span class="hljs-comment"># ssl_ciphers HIGH:!aNULL:!MD5;</span><br> <span class="hljs-comment"># ssl_prefer_server_ciphers on;</span><br><br> <span class="hljs-comment"># location / {</span><br> <span class="hljs-comment"># root html;</span><br> <span class="hljs-comment"># index index.html index.htm;</span><br> <span class="hljs-comment"># }</span><br> <span class="hljs-comment">#}</span><br><br>}<br></code></pre></td></tr></table></figure><p>现在,我们完成了 Nginx 的配置,是时候开始加密我们的连接了。</p><h1 id="四、SSL-证书的获取"><a href="#四、SSL-证书的获取" class="headerlink" title="四、SSL 证书的获取"></a>四、SSL 证书的获取</h1><p>HTTPS 依赖 SSL 证书进行加密。所以,在配置加密之前,我们必须先获得一个有效的 SSL 证书。</p><h2 id="1-由-CA-签发的证书"><a href="#1-由-CA-签发的证书" class="headerlink" title="1.由 CA 签发的证书"></a>1.由 CA 签发的证书</h2><p>想要获得可信的 SSL 证书,通常需要你向 CA 申请。但这并不是免费的,一张 SSL 证书从几百元到上千元不等,而且还是有有效期的。</p><p>毫无疑问的,这对于一般的个人来说成本太高了,但是我们同样还有许多免费 SSL 证书可以选择,它们同样可信,不过有一些缺点:</p><ol><li>通常无法获得免费的泛域名证书。</li></ol><blockquote><p>泛域名是什么?e.g.,*.example.com</p></blockquote><p>这意味着你必须给每个需要使用 HTTPS 的子域申请签发证书。当然,一般情况下,这并不是非常麻烦。</p><ol start="2"><li>常见地免费证书的有效期通常只有一年。这意味着你每年都得更换证书,一旦你忘记,证书过期后你的站点就会被提示不安全,尽管此时信息的传输仍被保护,但可能无法验证服务器的身份。</li></ol><p>当然,这些缺点几乎算不上缺点,比起几百上千的付费证书,这算缺点吗?要啥自行车!</p><p>现在我们以 TrustAsia 为例,演示如何申请签发一张 CA 证书。</p><p>考虑到安全性,笔者推荐你通过腾讯云申请 TrustAsia 免费证书。当然,如果你没有且不想注册腾讯云,你也可以选择 <a href="https://freessl.cn/">FreeSSL.cn</a>。但请注意,笔者并不熟悉也并不推荐使用本网站签发证书。</p><p>接下来我们假设你已经登陆好了腾讯云切到了控制台打开了 SSL 证书的管理页面(当然如果你没有可以 <a href="https://console.cloud.tencent.com/certoverview/">点此跳转</a>),你将看到以下界面:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_6.png" alt="腾讯云 SSL 证书管理页面"></p><p>切换至图中框住的 <code>我的证书</code> 选项卡,你将看到以下界面:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_7.png" alt="“我的证书” 选项卡"></p><p>单击图中框住的 <code>申请免费证书</code> 按钮,在弹出的 <code>确认证书类型</code> 窗口中选择 <code>免费版</code> 并点击确定。然后你将看到以下界面:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_8.png" alt="申请免费证书页面"></p><p>建议你除了改动绑定的域名和申请邮箱外按图中配置填写。填写完成后,点击 <code>提交申请,进行域名验证</code> 来进行下一步。</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_9.png" alt="域名验证页面"></p><p>接着,我们需要前往 DNS 服务提供商处添加一条 CA 指定的 DNS 记录,记录内容可以从域名验证页面获取。</p><p>添加完成后,等待 CA 验证并等着腾讯云给你发邮件即可。</p><p>当腾讯云通知你审核通过时,回到 <code>我的证书</code> 页面,就可以看到申请的 SSL 证书了。</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_10.png" alt="审核通过后的 SSL 证书"></p><p>单击图中框出的 <code>下载</code>,在弹出的页面中下载 <code>Nginx</code> 版本的证书。</p><p>记住,保管好你下载的证书文件,千万不要让私钥(e.g. <code>example.com.key</code>)泄露,否则你就只能吊销这个证书了。</p><p>现在你就获得了一个由 CA 签发的 SSL 证书。</p><h2 id="2-自签名的-SSL-证书"><a href="#2-自签名的-SSL-证书" class="headerlink" title="2.自签名的 SSL 证书"></a>2.自签名的 SSL 证书</h2><p>你还可以自己充当 CA,自己给自己签发 SSL 证书。这虽然可以加密传输的信息,但却不能完全阻止中间人攻击。</p><p>为什么呢?因为你的用户不知道你是不是你。自签名的 SSL 证书很难对服务器的身份进行验证,也就是说可能出现这样的情况: </p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_11.png" alt="自签名证书被中间人攻击"></p><p>换句话说,你能签发证书那不法分子一样能签发证书,用户怎么知道证书是不是你签发的?</p><p>但如果你使用的是 CA 签名的证书,就可能出现这样的情况:</p><p><img src="//initialheart.oss.aunly.cn/img/p3/img_12.png" alt="CA 证书被中间人攻击"></p><p>CA 签发的证书因为存在证书链,而可信 CA 的根证书预装在了每台设备中,即意味着这个证书的签发被 CA 认可,而 CA 认可身份并签发证书需要严格的审核,这就保障了这个证书就是你本人申请的证书,而使用者默认是你本人。这也是为什么你必须保管好你的私钥,私钥一旦泄露,CA 签发的证书也就失去了验证“你是你”的作用。</p><p>所以笔者不推荐使用自签名证书,如果你想了解相关信息,可以使用搜索引擎查询。</p><h1 id="五、使用-SSL-证书对连接进行加密"><a href="#五、使用-SSL-证书对连接进行加密" class="headerlink" title="五、使用 SSL 证书对连接进行加密"></a>五、使用 SSL 证书对连接进行加密</h1><p>不管通过哪种方式取得了 SSL 证书,拿了证书总是要用的,接下来我们来使用它。</p><p>假设你从腾讯云申请证书,证书已经解压到 <code>conf\ssl</code>。</p><p>让我们回到刚刚推荐的配置文件中,不知道你是否注意到了这个部分:</p><figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs 1c"><span class="hljs-meta">#server {</span><br><span class="hljs-meta"># listen 443 ssl;</span><br><span class="hljs-meta"># server_name localhost;</span><br><br><span class="hljs-meta"># ssl_certificate cert.pem;</span><br><span class="hljs-meta"># ssl_certificate_key cert.key;</span><br><br><span class="hljs-meta"># ssl_session_cache shared:SSL:1m;</span><br><span class="hljs-meta"># ssl_session_timeout 5m;</span><br><br><span class="hljs-meta"># ssl_ciphers HIGH:!aNULL:!MD5;</span><br><span class="hljs-meta"># ssl_prefer_server_ciphers on;</span><br><br><span class="hljs-meta"># location / {</span><br><span class="hljs-meta"># root html;</span><br><span class="hljs-meta"># index index.html index.htm;</span><br><span class="hljs-meta"># }</span><br><span class="hljs-meta">#}</span><br></code></pre></td></tr></table></figure><p>没错,这部分就是至关重要的加密部分!</p><p>假设我的域名是 <code>example.com</code>,将上面的部分修改为下面的样子:</p><figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs nginx"><span class="hljs-section">server</span> {<br> <span class="hljs-attribute">listen</span> <span class="hljs-number">443</span> ssl;<br> <span class="hljs-attribute">server_name</span> localhost;<br><br> <span class="hljs-attribute">ssl_certificate</span> example.com_bundle.pem;<br> <span class="hljs-attribute">ssl_certificate_key</span> example.com.key;<br><br> <span class="hljs-attribute">ssl_session_cache</span> shared:SSL:<span class="hljs-number">1m</span>;<br> <span class="hljs-attribute">ssl_session_timeout</span> <span class="hljs-number">5m</span>;<br><br> <span class="hljs-attribute">ssl_ciphers</span> HIGH:!aNULL:!MD5;<br> <span class="hljs-attribute">ssl_prefer_server_ciphers</span> <span class="hljs-literal">on</span>;<br><br> <span class="hljs-section">location</span> / {<br> <span class="hljs-attribute">proxy_pass</span> http://127.0.0.1:80;<br> <span class="hljs-attribute">proxy_set_header</span> Host <span class="hljs-variable">$proxy_host</span>;<br> <span class="hljs-attribute">proxy_set_header</span> X-Real-IP <span class="hljs-variable">$remote_addr</span>;<br> <span class="hljs-attribute">proxy_set_header</span> X-Forwarded-For <span class="hljs-variable">$proxy_add_x_forwarded_for</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><p>其中,<code>location</code> 里面的 <code>80</code> 端口可以改为你服务的端口,如果它不在 <code>80</code> 的话。同样的,你可以把开头 <code>listen</code> 中的 <code>443</code> 改为其他端口。</p><p>不过要注意,有些时候你可能需要在 <code>location</code> 中加上一行:</p><figure class="highlight pgsql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs pgsql">add_header Content-<span class="hljs-keyword">Security</span>-<span class="hljs-keyword">Policy</span> upgrade-insecure-requests;<br></code></pre></td></tr></table></figure><p>它的作用是将网页中所有的 HTTP 内容自动升级为 HTTPS 内容,这么做的原因是在 HTTPS 连接中不允许再通过 HTTP 传输数据。</p><p>一定要记得对齐缩进!</p><p>现在,打开 <code>nginx.exe</code>,启动 Nginx。</p><p>现在你就成功的使用 Nginx 反向代理加密了你的连接。</p><p>Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>《明日方舟》机器人(其实是 QQBot 框架) Amiya-Bot 简明部署教程</title>
<link href="/2022/8d92a2feb3e2/"/>
<url>/2022/8d92a2feb3e2/</url>
<content type="html"><![CDATA[<p> 在 CQ 还没凉那会儿笔者就在折腾 QQBot 了,第一次整 Bot 至今得有个七八年了,但是 CQ 凉了之后就没整了,很巧的是那会入坑了方舟(被朋友拖进来的),后来见着了一个能合成游戏内抽卡图的机器人,首先就觉得惊奇,CQ 都凉了机器人是越来越罕见,然后觉得这玩意儿挺好,我得整一个。</p><p> 那会这个机器人,也就是 Amiya-Bot,才刚 v3,笔者尝试部署,然后就被文档整懵了,遂放弃。</p><p> 真正的第一次成功部署在 v4,那时数据库改成了 sqlite,免配置。</p><p> 现在这个项目的最新稳定版本是 v5,截至截稿之时 v6 发布了第二个 Alpha 版本。(2022-09-23 更新:v6 已更新至 Beta2,现在我们推荐你选择 v6!)</p><p> 废话说得太多了,现在开始讲如何部署。</p><p> 在开始之前,需要说明的是,笔者因为自己就被文档坑过,所以为该项目完善了一些文档,下面可能会大量引用(当然,引用的文档不一定是笔者编写的),直接放上相关链接来看,本文只重点讲解文档没有涉及到的部分,比如 mirai 的部署和配置。引用的来自 AmiyaBot 的文档与本文采用相同方式许可。</p><h3 id="1-概述"><a href="#1-概述" class="headerlink" title="1. 概述"></a>1. 概述</h3><p> 笔者在 Windows 环境下部署并编写本文,所以使用 Linux 的用户可能不能照抄,但是思路是一样的,抄个思路一般也没问题,不过要注意你的系统是否符合项目要求,具体系统要求如下:</p><div class="note note-warning"> <ul><li>仅支持 <strong>Windows 7</strong> 以上系统</li><li>仅支持 <strong>MacOS 10.14 Mojave</strong> 以上系统</li><li>Linux 系统仅支持 <strong>Ubuntu 18.04</strong> 以及 <strong>Ubuntu 20.04</strong></li></ul> </div><p> 其他的系统部分用户有成功部署的案例,但是显然不完全适用本文,如果你的系统不符合以上要求,你可以参照本文也就是一般部署的思路尝试部署在你的系统,但是可能会遇到一些困难。</p><p> 在初次部署时你必须要有一台可用的手机,而之后若遇到滑动验证码可以选择使用手机通过或查阅下方高级使用部分的电脑通过。</p><p> 在开始正式部署前,我们有必要先了解一下项目的基本情况,否则可能会造成一些困扰。</p><p> Amiya-Bot 是基于 mirai-api-http 的 Python “《明日方舟》机器人”(其实你完全可以把 ta 当一个机器人框架使用)。</p><p> 那么,mirai-api-http是什么?mirai-api-http(下称 MAH 或 mah) 是 mirai-console 的一个插件,原生的 mirai-console 插件使用 kt 或 java 编写,mirai-api-http 通过提供 API 的方式让更多语言可以接入 mirai-console。</p><p> mirai 的相关介绍,由于其项目 README 有些限制,我不好引用,所以请 <a href="https://github.com/mamoe/mirai">自己去看</a> </p><p> 2022-09-23 补充一句:本文系在 2022-08-21 完成大部分内容的编写的,当时项目的最新生产版本为 v5。所以本文,包括下方高级使用与二次开发中提到的对于 AmiyaBot 的部分都存在一个前提,即在 v5 下。现在,我强烈推荐你选择即将完工的 v6。具体事项请参阅 <code>部署 Amiya-Bot</code> 部分。Good luck! </p><p> 2022-12-19 补充:近期 v5 相关文档已经不再提供,故本文删除了关于 v5 的内容。另新增了 mirai 报 <code>QQ版本过低</code> 的解决方案。</p><p> 那么基本情况就介绍到这里,接下来开始正式的部署。</p><h3 id="2-部署-mirai"><a href="#2-部署-mirai" class="headerlink" title="2. 部署 mirai"></a>2. 部署 mirai</h3><p> 都说 Amiya-Bot 基于 mirai-api-http 了,那当然先得从“基于”开始做起嘛。就好像盖房子总得先盖地基一样,而 mirai-api-http 又基于 mirai-console (一般用户方便理解可以直接看作 mirai 本体),mirai 就像地基填的混凝土,而 mah 则是钢筋。所以我们先来进行混凝土的制作,也就是 mirai 的部署。</p><p> 部署 mirai 对于一般用户来说就是部署 mirai-console,mirai-console 有个启动器叫做 Mirai Console Loader 简称 MCL(下称可能为 mcl),而 MCL 又有个安装器叫做 MCL Installer(下称 MCLI 或 mcli),所以我们现在先去下载 MCL Installer。</p><p> 打开 <a href="https://github.com/iTXTech/mcl-installer/releases">此页面</a>,找到最新的稳定 Release,下载对应你系统的版本。</p><p> 一般情况下,请下载含有 <code>x86</code> 的版本而不是 <code>arm64</code>。</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img.png" alt="Release,截至截稿时最新稳定版本为 1.0.7"></p><p> 下载完之后复制到你准备用来放 mirai 的目录,然后打开它。可能会弹出 UAC 警告,请确定。</p><p> 然后你会看到以下界面:</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_1.png" alt="mcli 的初始界面"></p><p> 通常来说,如果你不是跟 Java 相关的开发者,是不会有如此高的 Java 版本的,最可能出现的是 <code>1.8.0</code> 甚至是没有 Java,那么笔者假设自己是 <code>1.8.0</code>,并不满足 mirai 推荐的 Java 版本,所以我们输入 <code>Y</code> 并回车(当然如果你安装了版本 ≥11 的 JDK 那么可以选择输入N,但,Java 算不上大,独立隔离不影响系统的最新 Java 谁不爱呢?)。</p><p> 接下来会让你选择一系列选项,不一一放图讲解了,针对每个选项进行说明:</p><p> Java 版本:推荐是能选到的最高,原因有多方面不展开讲,也许有机会会单独讲。</p><p> JRE or JDK:推荐 <code>JDK</code>,不解释。</p><p> Binary Architecture:通常来说,请输入 <code>x64</code> 而不是默认的 <code>x32</code>,这十分重要。</p><p> 然后会开始 Java 的下载,下载完后会出现 MCL 的公告,并有最新的 MCL 版本,询问你是否下载 MCL ,那当然是毫无疑问的选择 <code>Y</code>。</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_2.png" alt="mcli 询问是否下载 MCL,截至截稿时最新版本为 2.1.0"></p><p> 选择好之后,很快会下载完成,按任意键就可以退出 MCLI,这个时候你可以安全的删除 MCLI 主程序。</p><p> 现在你已经做好了混凝土中的水泥,是时候找一些砂石混进去了,接下来就是配置了。</p><h3 id="3-配置-MCL"><a href="#3-配置-MCL" class="headerlink" title="3. 配置 MCL"></a>3. 配置 MCL</h3><p> 首先,我们要弄清楚如果你正确安装了 MCL,安装文件夹的目录结构是怎样的。</p><p> 在没有第一次运行 mcl 执行初始化时,安装目录结构如下:</p> <figure class="highlight dos"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs dos">注:已删除 mcli<br> <br>├─ LICENSE <br>├─ README.<span class="hljs-built_in">md</span> <br>├─ java <br>├─ mcl <br>├─ mcl.<span class="hljs-built_in">cmd</span> <br>└─ mcl.jar<br></code></pre></td></tr></table></figure><p> 现在我们要执行一次 mcl 以初始化,双击打开 <code>mcl.cmd</code>,你将看到以下界面:</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_3.png" alt="mcl 自动下载最新的基础组件"></p><p> 在第一次启动 mcl 时,mcl 会自动下载最新的必要库或插件,列表如下:</p> <figure class="highlight stylus"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs stylus">net<span class="hljs-selector-class">.mamoe</span>:mirai-console<br>net<span class="hljs-selector-class">.mamoe</span>:mirai-console-terminal<br>net<span class="hljs-selector-class">.mamoe</span>:mirai-core-<span class="hljs-attribute">all</span><br>org<span class="hljs-selector-class">.itxtech</span>:mcl-addon<br></code></pre></td></tr></table></figure><p> 当完成初始化(mirai 启动成功)时,控制台会输出消息 <code>mirai-console started successfully.</code>。当你看到这条消息时,你就可以把 mcl 的窗口关上了。</p><p> 完成初始化后,安装目录结构如下:</p> <figure class="highlight mipsasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs mipsasm">├─ LICENSE<br>├─ README.md<br>├─ <span class="hljs-built_in">config</span><br>├─ <span class="hljs-built_in">config</span>.<span class="hljs-keyword">json</span><br><span class="hljs-keyword"></span>├─ data<br>├─ <span class="hljs-keyword">java</span><br><span class="hljs-keyword"></span>├─ libs<br>├─ logs<br>├─ mcl<br>├─ mcl.cmd<br>├─ mcl.<span class="hljs-keyword">jar</span><br><span class="hljs-keyword"></span>├─ plugin-libraries<br>├─ plugin-<span class="hljs-keyword">shared-libraries</span><br><span class="hljs-keyword"></span>└─ plugins<br></code></pre></td></tr></table></figure><p> 进入 <code>config\Console</code> 目录,打开 <code>AutoLogin.yml</code>,根据注释配置账号密码。</p><p> 请注意密码应填在 <code>value</code> 项而非 <code>kind</code>,参数名称后的冒号后有一个空格。</p><p> 假设我的账号是 <code>10001</code>,我的密码是 <code>mhtnbdhouse</code>,那么我应该这样填写配置:</p> <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-attr">accounts:</span> <br><span class="hljs-bullet">-</span> <span class="hljs-comment"># 账号, 现只支持 QQ 数字账号</span><br> <span class="hljs-attr">account:</span> <span class="hljs-number">10001</span><br> <span class="hljs-attr">password:</span> <br> <span class="hljs-comment"># 密码种类, 可选 PLAIN 或 MD5</span><br> <span class="hljs-attr">kind:</span> <span class="hljs-string">PLAIN</span><br> <span class="hljs-comment"># 密码内容, PLAIN 时为密码文本, MD5 时为 16 进制</span><br> <span class="hljs-attr">value:</span> <span class="hljs-string">mhtnbdhouse</span><br> <span class="hljs-comment"># 账号配置. 可用配置列表 (注意大小写):</span><br> <span class="hljs-comment"># "protocol": "ANDROID_PHONE" / "ANDROID_PAD" / "ANDROID_WATCH" / "MACOS" / "IPAD"</span><br> <span class="hljs-comment"># "device": "device.json"</span><br> <span class="hljs-comment"># "enable": true</span><br> <span class="hljs-comment"># "heartbeatStrategy": "STAT_HB" / "REGISTER" / "NONE"</span><br> <span class="hljs-attr">configuration:</span> <br> <span class="hljs-attr">protocol:</span> <span class="hljs-string">ANDROID_PHONE</span><br> <span class="hljs-attr">device:</span> <span class="hljs-string">device.json</span><br> <span class="hljs-attr">enable:</span> <span class="hljs-literal">true</span><br> <span class="hljs-attr">heartbeatStrategy:</span> <span class="hljs-string">STAT_HB</span><br></code></pre></td></tr></table></figure><p> 配置好之后保存退出。</p><p> 接下来再次打开 mcl,在一段时间的加载后会弹出这样的一个窗口:</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_4.png" alt="mirai 的验证码弹窗 图片由用户友情提供"></p><p> 写得很清楚,“需要滑动验证码”,那么应该怎么获得 mirai 需要的 ticket 呢?</p><p> 既然你是冲着这个教程来的,当然是先介绍最简单的方法!点击图中的 <code>Open with TxCaptchaHelper</code> 按钮,会弹出一个新的窗口:</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_5.png" alt="TxCaptchaHelper 请求码弹窗 图片由用户友情提供"></p><p> 你可以在 <a href="https://github.com/mzdluo123/TxCaptchaHelper/releases">这里</a> 下载到手机端,1.3 或者 1.2 任选(截稿时的最新版是 1.3,笔者使用 1.2,因为笔者死活上不去 AppCenter)。</p><p> 拿出你的手机,安装上面的手机端,然后打开它,它的界面是这样的:</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_6.png" alt="滑动验证助手界面 图片由用户友情提供"></p><p> 输入上面要求要输的请求码,点下一步,会跳转验证码界面,完成之后会自动上传到服务器,服务器将 ticket 下发到你的机器,验证就通过了!十分地简单!</p><p> 接下来你大概会疑惑:怎么又弹了个窗?</p><p> 这次可不是验证码,这次是设备锁:</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_7.png" alt="设备锁弹窗 图片由用户友情提供"></p><p> 想通过设备锁有很多种方法,但都有一个前提要求:手机与电脑在同一网络环境下(出口 IP 最好相同),而如果你的机器不在你身边,还有替代方法可以让你和机器 <code>统一出口 IP</code>,但是我不能也不敢展开讲,懂得都懂。</p><p> 简单口述两种最简单的方法:</p><p> ①将链接直接复制进浏览器打开,拿出手机登录账号扫码验证。</p><p> ②将链接发送至手机,在 QQ 中打开此链接(登录此账号)进行验证。(你可以用将链接发给你自己等方式在 QQ 中打开链接)</p><p> 在通过设备锁之后, MCL 的配置就完成了,你已经制作好了混凝土,接下来要浇灌地基了,我们接着来安装 MAH。</p><h3 id="4-安装-mirai-api-http"><a href="#4-安装-mirai-api-http" class="headerlink" title="4. 安装 mirai-api-http"></a>4. 安装 mirai-api-http</h3><p> 安装 mirai-api-http 有两种方式,一种是使用 MCL 安装,另一种是手动安装,笔者使用的是手动安装,因为手动安装通常会更稳定,不会被 MCL 更新,毕竟生产环境求稳为上。</p><h4 id="I-使用-MCL-安装"><a href="#I-使用-MCL-安装" class="headerlink" title="I. 使用 MCL 安装"></a>I. 使用 MCL 安装</h4><p> 这十分地简单。</p><p> Win + R 输入 cmd 回车打开命令提示符,切换到 MCL 安装目录,输入:</p> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs shell">mcl --update-package net.mamoe:mirai-api-http --channel stable-v2 --type plugin<br>mcl -u<br></code></pre></td></tr></table></figure><p> 即可安装 MAH 的最新版本。</p><p> 如果你不会切换目录,你可以在安装目录下新建一个 <code>mah.txt</code>,填入上面的命令后保存,将 <code>mah.txt</code> 改为 <code>mah.bat</code>,警告选是,然后双击运行它即可。</p><div class="note note-info"> <p>没有发现 .txt?那意味着你没有开启已知文件的后缀显示,请百度 <code>Windows 开启后缀显示</code>。</p> </div><p> 当出现消息 <code>mirai-console started successfully.</code> 时,你可以在 mcl 中输入 <code>exit</code> 或者 <code>stop</code> 来安全退出,一般推荐以此种方式关闭 mcl。</p><h4 id="II-手动安装"><a href="#II-手动安装" class="headerlink" title="II. 手动安装"></a>II. 手动安装</h4><p> 这稍微麻烦一些,但并不难,如果你无法使用第一种方式或者不想用等种种原因,你可以使用手动安装。</p><p> 首先,打开 mah 的 <a href="https://github.com/project-mirai/mirai-api-http/releases">Release</a>,下载最新的稳定版本,相关操作与上面 MCLI 类似,不再赘述。</p><p> 就像 Minecraft 安装 Mod 一样,手动安装 Mirai 插件也只需要将 jar 文件拖入 <code>plugins</code> 文件夹即可,然后请按初始化 MCL 的方式操作一遍来生成配置。</p><p> 无论你选择哪一种方法安装,安装并初始化 MAH 完成后,混凝土车已经到场,只差最后的方案了,接下来我们进行 MAH 的配置。</p><h3 id="5-配置-mirai-api-http"><a href="#5-配置-mirai-api-http" class="headerlink" title="5. 配置 mirai-api-http"></a>5. 配置 mirai-api-http</h3><p> 就像之前配置过的 <code>Autologin.yml</code> 一样,配置 MAH 也有一些不变的基本原则,也就是 yaml 的格式。</p><p> 记住,<strong>参数冒号后边一定要加一个空格!!!</strong></p><p> 这是易错项,总是有用户报这个错自己查了好久最后发现少了个空格。</p><p> 作为一般用户,你不需要知道 MAH 中的全部配置项意思,实际上对一般用户而言,唯一需要变动的可能就是 <code>verifyKey</code>,可以简单理解为密码。</p><p> 直接粘贴下面的配置,并改动 <code>verifyKey</code> 即可。</p> <figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs yaml"><span class="hljs-comment">## 启用的 adapter, 内置有 http, ws, reverse-ws, webhook</span><br><span class="hljs-attr">adapters:</span><br> <span class="hljs-bullet">-</span> <span class="hljs-string">http</span><br> <span class="hljs-bullet">-</span> <span class="hljs-string">ws</span><br><br><span class="hljs-comment">## 是否开启认证流程, 若为 true 则建立连接时需要验证 verifyKey</span><br><span class="hljs-comment">## 建议公网连接时开启</span><br><span class="hljs-attr">enableVerify:</span> <span class="hljs-literal">true</span><br><span class="hljs-attr">verifyKey:</span> <span class="hljs-number">1234567890</span><br><br><span class="hljs-comment">## 开启一些调式信息</span><br><span class="hljs-attr">debug:</span> <span class="hljs-literal">false</span><br><br><span class="hljs-comment">## 是否开启单 session 模式, 若为 true,则自动创建 session 绑定 console 中登录的 bot</span><br><span class="hljs-comment">## 开启后,接口中任何 sessionKey 不需要传递参数</span><br><span class="hljs-comment">## 若 console 中有多个 bot 登录,则行为未定义</span><br><span class="hljs-comment">## 确保 console 中只有一个 bot 登陆时启用</span><br><span class="hljs-attr">singleMode:</span> <span class="hljs-literal">false</span><br><br><span class="hljs-comment">## 历史消息的缓存大小</span><br><span class="hljs-comment">## 同时,也是 http adapter 的消息队列容量</span><br><span class="hljs-attr">cacheSize:</span> <span class="hljs-number">4096</span><br><br><span class="hljs-comment">## adapter 的单独配置,键名与 adapters 项配置相同</span><br><span class="hljs-attr">adapterSettings:</span><br> <span class="hljs-comment">## 详情看 http adapter 使用说明 配置</span><br> <span class="hljs-attr">http:</span><br> <span class="hljs-attr">host:</span> <span class="hljs-string">localhost</span><br> <span class="hljs-attr">port:</span> <span class="hljs-number">8080</span><br> <span class="hljs-attr">cors:</span> [<span class="hljs-string">"*"</span>]<br> <span class="hljs-attr">unreadQueueMaxSize:</span> <span class="hljs-number">100</span><br> <br> <span class="hljs-comment">## 详情看 websocket adapter 使用说明 配置</span><br> <span class="hljs-attr">ws:</span><br> <span class="hljs-attr">host:</span> <span class="hljs-string">localhost</span><br> <span class="hljs-attr">port:</span> <span class="hljs-number">8060</span><br> <span class="hljs-attr">reservedSyncId:</span> <span class="hljs-number">-1</span><br></code></pre></td></tr></table></figure><p> 好了,现在你已经打好了地基,可以在上面建房子了。接下来我们进行 Amiya-Bot 的部署。</p><h3 id="6-部署-Amiya-Bot"><a href="#6-部署-Amiya-Bot" class="headerlink" title="6. 部署 Amiya-Bot"></a>6. 部署 Amiya-Bot</h3><p> 折腾了这么久,总算是轮到部署 Amiya-Bot 了!但是……Amiya-Bot 有完备的文档,直接查阅项目官网即可。</p><p> <a href="https://www.amiyabot.com/guide/deploy/getStarted.html">请看这里</a></p><p> 敬请留意:不久后我们可能会彻底停止 v5 版本的维护,届时 v5 版本的官网可能会更改为现在 AmiyaBot 框架官网的镜像。</p><p> 笔者十分推荐你使用代码部署而不是 exe (Windows 可执行文件) 部署,因为代码会比打包好的 exe 灵活得多(虽然这会需要你配置 Python 环境)。</p><p> 就这样。</p><p> 本文开头已经说了:</p><blockquote><p>在开始之前,需要说明的是,笔者因为自己就被文档坑过,所以为该项目完善了一些文档,下面可能会大量引用(当然,引用的文档不一定是笔者编写的),直接放上相关链接来看,本文只重点讲解文档没有涉及到的部分,比如 mirai 的部署和配置。</p></blockquote><p> 所以其实这篇文章其实主要是讲的 mirai 和 mah 的搭建和配置。</p><p> 不过还是补充几个要点:</p><ul><li>推荐下载 Python 3.8,务必将其添加进环境变量(安装时勾选 <code>Add PATH</code> 之类的选项)!</li><li>不要忘记还有个 <code>Playwright</code> 需要安装浏览器内核,pip 安装好依赖之后命令行输入:</li></ul> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">playwright install chromium<br></code></pre></td></tr></table></figure><p> 在部署过程中遇到其他问题可以加入项目的官方频道或者发电邮到 <code>[email protected]</code>。</p><h3 id="7-高级使用与二次开发"><a href="#7-高级使用与二次开发" class="headerlink" title="7. 高级使用与二次开发"></a>7. 高级使用与二次开发</h3><h4 id="I-高级使用"><a href="#I-高级使用" class="headerlink" title="I. 高级使用"></a>I. 高级使用</h4><h5 id="①-数据库"><a href="#①-数据库" class="headerlink" title="①. 数据库"></a>①. 数据库</h5><p> 如果你的用户很多,默认的 <code>Sqlite</code> 无法满足你的需求,你还可以使用 <code>Mysql</code>。</p><h6 id="v6"><a href="#v6" class="headerlink" title="v6"></a>v6</h6><p> 请参阅 <a href="https://www.amiyabot.com/guide/deploy/advanced/mysql.html">项目文档</a></p><h5 id="②-添加表情"><a href="#②-添加表情" class="headerlink" title="②. 添加表情"></a>②. 添加表情</h5><p> 不知道你是否注意到了,当你发送 <code>兔兔</code> 这类呼叫而不触发任何功能的语句时,Amiya 会随机回复一些表情包。这些表情包同样是可以自由增减的。</p><h6 id="v6-1"><a href="#v6-1" class="headerlink" title="v6"></a>v6</h6> <div class="note note-warning"> <p>请确定你已安装 <span class="label label-info">兔兔互动</span> 插件。</p> </div><p> 将想要添加的图片放入 <code>plugins\amiyabot-user\face</code> 中即可,支持 <code>GIF</code>。</p><div class="note note-warning"> <p>上面的路径省略了版本号。</p> </div><h5 id="③-手动获取验证码-ticket"><a href="#③-手动获取验证码-ticket" class="headerlink" title="③. 手动获取验证码 ticket"></a>③. 手动获取验证码 ticket</h5><p> 有时候可能你不方便或者懒得使用手机通过验证码,你还可以使用电脑手动获得 ticket。</p><div class="note note-info"> <p>为什么初次部署要求你一定要有手机?因为随后还有设备锁等着你。</p> </div><p> 以 Microsoft Edge 为例,当弹出滑动验证码窗口时,复制验证码链接到浏览器打开,并按 <code>F12</code> 打开开发人员工具,切换到 <code>网络</code> 选项卡(老版本的浏览器可能显示为 <code>Network</code>)。</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_8.png" alt="抓包"></p><p> 此时通过滑动验证码,如果页面没有显示空白而是要求你再次通过验证码,再次通过即可;在打开的开发人员工具中找到 <code>cap_union_new_verify</code>,如果你通过了多个验证码则找按时间线升序排列最底下也就是最新的那一个,双击后切换到 <code>响应</code> 选项卡,写着 <code>ticket</code> 的后面引号部分则是 ticket,注意不含前后的引号。</p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_9.png" alt="在通过多个验证码之后找到最新的 cap_union_new_verify"></p><p> <img src="//initialheart.oss.aunly.cn/img/p2/img_10.png" alt="获得 ticket"></p><h4 id="II-二次开发"><a href="#II-二次开发" class="headerlink" title="II. 二次开发"></a>II. 二次开发</h4><p> 在本文的开头说到,你完全可以将 Amiya-Bot 当作机器人框架来使用。</p><p> 如果你有 Python 基础,又想开发属于自己的个性化功能,你可以查阅项目的开发文档。</p><p> <a href="https://www.amiyabot.com/develop/basic/">v6 开发文档(推荐!)</a></p><h3 id="8-常见问题"><a href="#8-常见问题" class="headerlink" title="8. 常见问题"></a>8. 常见问题</h3><p> 暂时没想到什么问题,因为大多数情况已经在文中写明。</p><p> 如果你有任何问题,欢迎在评论区提出,如果有必要的话它将会出现在这里。</p><p> 当然,由于情况随时间发生变化而造成的问题也会在这里提出。</p><h4 id="Ⅰ-使用一段时间后-mirai-提示-“QQ-版本过低”"><a href="#Ⅰ-使用一段时间后-mirai-提示-“QQ-版本过低”" class="headerlink" title="Ⅰ. 使用一段时间后 mirai 提示 “QQ 版本过低”"></a>Ⅰ. 使用一段时间后 mirai 提示 “QQ 版本过低”</h4><p> 似乎是因为腾讯侧的变动。截至本方案发布 (2022-12-19) 时未发现 mirai 修复此问题。</p><p> 临时解决方案:</p><p> 删除 <code>{mcl根目录}/bots/{你的 Bot QQ号}/device.json</code>,重启 mirai。</p><p> 还可以添加 <a href="https://github.com/cssxsh/mirai-device-generator">cssxsh/mirai-device-generator</a> 插件,以生成可能更可靠的 <code>device.json</code>。</p><p> 另外,如果你对 mirai 的插件没有强需求,可以转至 gocq 以解决该问题。gocq 用户目前没有相关问题的报告。</p><p> 如果你想转至 gocq,参照 <a href="https://www.amiyabot.com/guide/deploy/yourChoose.html#%E4%BD%BF%E7%94%A8-go-cqhttp">这里</a></p><p> Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
<entry>
<title>Windows 10/Windows Server 2016+ GPG 签名简明部署教程</title>
<link href="/2022/9376496fa4da/"/>
<url>/2022/9376496fa4da/</url>
<content type="html"><![CDATA[<p> 前两天我在服务器上安装完 Git 向 Github 提交 SSH Key 时注意到底下出现了一个叫做 “GPG” 的东西,略微看了一眼描述发现这似乎这是用来验证身份的数字签名,我一下就来了兴趣,开始跟着 Github 的文档折腾这个对我来说还算新鲜的玩意儿。</p><h3 id="1-安装-GPG"><a href="#1-安装-GPG" class="headerlink" title="1. 安装 GPG"></a>1. 安装 GPG</h3><p> 在安装 GPG 之前,显然我们要先搞明白 GPG 大致是个什么玩意儿: </p><p> GPG 是 GnuPG 的缩写,GnuPG 是 PGP 在 GPL 下的替代版本。Github 和 Gitee 等代码托管平台通常使用 GPG 为提交和标签签名(至少我看到的如此)。 这可以防止有人冒充你执行提交或者打标签,特别是可以保护标签的安全性。 </p><p> 要安装 GPG,首先当然要下载 GPG 的安装包,在<a href="https://gpg4win.org/download.html">此处</a>可以下载到。 </p><p> 需要注意的是,单击下载页面后,页面会要求你捐赠,选择 “Bank transfer” 后点击 “Download” 即可正常下载。当然如果你有能力的话还是建议你支持一下! </p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img.png" alt="下载页面"></p><p> 下载完成后打开安装向导,直接一路下一步即可,当然你可以根据你的需要更改安装路径,但无论是否更改,一定要记住它,马上就要用到。中间会弹出一个新的安装向导,也一路下一步即可,安装读完条之后关闭这个向导安装才能继续进行。</p><h3 id="2-GPG-配置"><a href="#2-GPG-配置" class="headerlink" title="2. GPG 配置"></a>2. GPG 配置</h3><p> 安装好 GPG 之后,通常你可以在你的桌面找到一个这样的东西:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_1.png" alt="Kleopatra 图标"></p><p> 这个叫做 “Kleopatra” 的玩意儿就是 GPG 的 GUI 界面,打开它,你将看到以下内容:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_2.png" alt="Kleopatra 界面"></p><p> 点击 “新建密钥对”,会弹出以下界面,按你情况填写,邮箱需要填你 Github 的绑定邮箱。</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_3.png" alt="新建密钥对界面"></p><p> 通常情况下,建议你勾选使用密码保护密钥以确保安全。填写完之后单击新建。</p><p> 如果你勾选了使用密码保护密钥,那么在单击新建之后你会看到这样的界面:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_4.png" alt="新建密钥中"></p><p> 输入你准备用来保护你密钥的密码,输两遍然后确认。</p><p> 稍等一会就可以了,新建完密钥对之后回到主页面如果你看到这样的页面说明你已经建好了密钥:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_5.png" alt="新建好密钥对的 Kleopatra 界面"></p><p> 那么就该进行下一步了。</p><h3 id="3-将你的密钥告诉-Git"><a href="#3-将你的密钥告诉-Git" class="headerlink" title="3. 将你的密钥告诉 Git"></a>3. 将你的密钥告诉 Git</h3><p> 要让 Git 在提交和新建标签时使用你的密钥签名,当然需要把你的密钥告诉 Git。</p><p> 回到 Kleopatra,找到你新建的密钥,看见 “密钥 ID” 那一行了吗?点击它并按下 Ctrl + C 以复制它。</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_6.png" alt="点它"></p><p> 将它粘贴到任意文本框内,将中间的所有空格删除,比如我的 ID 是 <code>847D 5CE3 630C D762</code>,那么需要处理成 <code>847D5CE3630CD762</code>。</p><p> 随后 Win+R 输入 cmd 回车打开命令提示符,输入:</p> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">git config --global user.signingkey 你刚刚处理过的密钥<br></code></pre></td></tr></table></figure><p> 例如,我刚刚的密钥是 <code>847D5CE3630CD762</code>,那么我输入:</p> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">git config --global user.signingkey 847D5CE3630CD762<br></code></pre></td></tr></table></figure><p> 按照 Github 的文档,配置到这里就结束了,但是其实并没有!在这时我尝试使用 Git 提交,但 Git 唤出 GPG 后 GPG 给了我一个大嘴巴子:</p> <figure class="highlight routeros"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs routeros">gpg: skipped <span class="hljs-string">"847D5CE3630CD762"</span>: <span class="hljs-literal">No</span><span class="hljs-built_in"> secret </span>key<br></code></pre></td></tr></table></figure><p> 看报错的意思是不存在这个密钥,这就奇怪了,明明我已经新建好了密钥,密钥 ID 也没有错误,为什么就是不行呢?我研究了很久,最后找到了问题的答案:需要告诉 Git 你安装 GPG 的位置!</p><p> 你还记得你在第一步时留下的安装路径吗?接下来就要用到它,打开安装目录下的 <code>bin</code> 文件夹,找到 GPG 的主程序(通常为 <code>gpg.exe</code>),接着在命令提示符中输入:</p> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">git config --global gpg.program "你的 GPG 主程序位置"<br></code></pre></td></tr></table></figure><p> 例如,我的安装路径在 <code>D:\Gnu\GPG\</code>,那么我输入:</p> <figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">git config --global gpg.program "D:\Gnu\GPG\bin\gpg.exe"<br></code></pre></td></tr></table></figure><p> 注意引号不能少!</p><p> 这样如果没有意外的话就可以正常使用你的密钥对你的提交或者标签签名了!</p><p> 在执行这些操作时如果你在创建密钥的时候选择了使用密码保护密钥则必须键入你的密钥密码,如果没有密码则无法使用,所以务必牢记你的密码!</p><p> 但是想要让 Github 认可你的签名,你还要将你的公钥告诉 Github。</p><h3 id="4-将你的密钥告诉-Github"><a href="#4-将你的密钥告诉-Github" class="headerlink" title="4. 将你的密钥告诉 Github"></a>4. 将你的密钥告诉 Github</h3><p> 再次回到 Kleopatra,右键你的密钥选择 “导出”:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_7.png" alt="右键导出"></p><p> 选择一个方便的路径,比如说桌面,检查文件名是否含有 “public” 字样,然后确定。</p><p> 找到刚刚导出的密钥,使用文本编辑器打开(如果你没法直接打开请把后缀改为 txt),然后暂且放在一边。</p><p> 打开 Github 首页,点击你的头像后选择 “Settings”</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_8.png" alt="Github 头像"></p><p> 打开 Settings 后在左侧找到 “SSH and GPG keys”:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_9.png" alt="Github Settings"></p><p> 点击 “New GPG keys”:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_10.png" alt="SSH and GPG keys"></p><p> 随便输入一个标题,把刚刚打开的密钥全部贴进去,然后点击 “Add GPG key”:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_11.png" alt="Add GPG key"></p><p> 这时通常会要求你进行身份验证,输入你的账户密码之后确认。</p><p> 然后就完成了!现在你的提交和标签会显示 “Verified” 字样。</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_12.png" alt="Verified!"></p><p> 如果你想进一步增强安全性,还可以回到刚才的 “SSH and GPG keys” 页面,将底部的 “Flag unsigned commits as unverified” 勾选上,这样未经你签名但是写着你账户信息的提交全部会被标记为 “Unverified”。</p><p> 但是务必注意,这会对你以前的提交产生影响,所以你可以在你的个人资料上做好说明,例如这样:</p><p> <img src="//initialheart.oss.aunly.cn/img/p1/img_13.png" alt="个人资料说明"></p><p> Enjoy!</p>]]></content>
<categories>
<category>技术</category>
<category>教程</category>
</categories>
</entry>
</search>