<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[李承武]]></title><description><![CDATA[在技术与艺术间随波逐流…]]></description><link>https://lichengwu.net/</link><image><url>http://lichengwu.net/favicon.png</url><title>李承武</title><link>https://lichengwu.net/</link></image><generator>Ghost 3.42</generator><lastBuildDate>Tue, 02 Jun 2026 01:16:59 GMT</lastBuildDate><atom:link href="https://lichengwu.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[NGINX反代MINIO配置，解决403 Forbidden]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>S3 Browser连接到MINIO API(9000端口)，使用MOVE等功能报403 Forbidden，一开始以为是Buckets或Access Keys的权限问题，后经测试无果，查看日志发现原来是NGINX报的403，测试了各种NGINX反代配置（包括<a href="https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html">MINIO官方NGINX反代配置</a>）还是报403，后经google发现<a href="https://github.com/1Panel-dev/1Panel/issues/3924">OpenResty反代MinIO的API端口无法进行上传等操作</a>这个issues</p>
<blockquote>
<p>因反代缓存将HEAD请求转换为GET请求进行缓存，导致HEAD请求403从而引发问题点</p>
</blockquote>
<p>解决方法只需在NGINX反代配置中加入<code>proxy_cache_convert_head off;</code></p>
<p>以下是结合官方推荐配置解决方案：</p>
<pre><code>location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_</code></pre>]]></description><link>https://lichengwu.net/nginx-minio-reverse-proxy-403-forbidden-solution/</link><guid isPermaLink="false">67666e437b683b0001830eda</guid><category><![CDATA[Nginx]]></category><category><![CDATA[minio]]></category><category><![CDATA[403 Forbidden]]></category><category><![CDATA[api]]></category><category><![CDATA[9000]]></category><category><![CDATA[S3 Browser]]></category><category><![CDATA[Access Keys]]></category><category><![CDATA[Buckets]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Sat, 21 Dec 2024 13:06:01 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>S3 Browser连接到MINIO API(9000端口)，使用MOVE等功能报403 Forbidden，一开始以为是Buckets或Access Keys的权限问题，后经测试无果，查看日志发现原来是NGINX报的403，测试了各种NGINX反代配置（包括<a href="https://min.io/docs/minio/linux/integrations/setup-nginx-proxy-with-minio.html">MINIO官方NGINX反代配置</a>）还是报403，后经google发现<a href="https://github.com/1Panel-dev/1Panel/issues/3924">OpenResty反代MinIO的API端口无法进行上传等操作</a>这个issues</p>
<blockquote>
<p>因反代缓存将HEAD请求转换为GET请求进行缓存，导致HEAD请求403从而引发问题点</p>
</blockquote>
<p>解决方法只需在NGINX反代配置中加入<code>proxy_cache_convert_head off;</code></p>
<p>以下是结合官方推荐配置解决方案：</p>
<pre><code>location / {
      proxy_set_header Host $http_host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;

      proxy_connect_timeout 300;
      # Default is HTTP/1, keepalive is only enabled in HTTP/1.1
      proxy_http_version 1.1;
      proxy_set_header Connection &quot;&quot;;
      chunked_transfer_encoding off;
      proxy_cache_convert_head off; # 解决403 Forbidden

      proxy_pass http://127.0.0.1:9000;
}
</code></pre>
<p>enjoy life</p>
<!--kg-card-end: markdown--><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[win7禁用Evernote自动升级更新]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><mark>2024.3.29</mark></p>
<p><strong>老版本win客户端已拒绝登录，官方回应win7唯一的选择只能使用Web客户端</strong></p>
<p><a href="https://discussion.evernote.com/forums/topic/151151-legacy-version-will-stop-working-windows-7/">Legacy version will stop working / windows 7</a></p>
<hr>
<p>Evernote自动升级后win7打开报错关键字：<strong>GetPackageFamilyName</strong> <strong>动态链接</strong> <strong>Kernel32.dll</strong></p>
<blockquote>
<p>逛Evernote官方论坛获知最新版本不再支持win7。</p>
</blockquote>
<p>下载Evernote官方版本<a href="https://cdn1.evernote.com/boron/win/builds/Evernote-10.56.8-win-ddl-ga-4069-8d752afa50-setup.exe">v10.56.8</a>重新安装可以继续在Win7上使用</p>
<h2 id="evernote">禁用Evernote自动升级更新</h2>
<p>打开<code>C:\Users\[your_username]\AppData\Local\Programs\Evernote\resources\app-update.yml</code>把里面的全部内容注释掉</p>
<!--kg-card-end: markdown-->]]></description><link>https://lichengwu.net/disable-evernote-automatic-update-on-win7/</link><guid isPermaLink="false">646fabae57b0dd00011b4630</guid><category><![CDATA[GetPackageFamilyName]]></category><category><![CDATA[Kernel32.dll]]></category><category><![CDATA[Evernote]]></category><category><![CDATA[win7]]></category><category><![CDATA[windows]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Thu, 25 May 2023 19:12:21 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><mark>2024.3.29</mark></p>
<p><strong>老版本win客户端已拒绝登录，官方回应win7唯一的选择只能使用Web客户端</strong></p>
<p><a href="https://discussion.evernote.com/forums/topic/151151-legacy-version-will-stop-working-windows-7/">Legacy version will stop working / windows 7</a></p>
<hr>
<p>Evernote自动升级后win7打开报错关键字：<strong>GetPackageFamilyName</strong> <strong>动态链接</strong> <strong>Kernel32.dll</strong></p>
<blockquote>
<p>逛Evernote官方论坛获知最新版本不再支持win7。</p>
</blockquote>
<p>下载Evernote官方版本<a href="https://cdn1.evernote.com/boron/win/builds/Evernote-10.56.8-win-ddl-ga-4069-8d752afa50-setup.exe">v10.56.8</a>重新安装可以继续在Win7上使用</p>
<h2 id="evernote">禁用Evernote自动升级更新</h2>
<p>打开<code>C:\Users\[your_username]\AppData\Local\Programs\Evernote\resources\app-update.yml</code>把里面的全部内容注释掉</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[从Strapi v3升级迁移到Strapi v4再到放弃]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>由于官方升级文档太一言难尽，而且自己项目基本就只用到GraphQL功能，所以自己尝试适合项目的简单升级迁移方法。</p>
<blockquote>
<p>我是从v3最新版本v3.6.11升级到<s>v4.7.1</s>v4.8.2，理论上v3.x到v3.6期间升级版本之间没有结构性的重大变动用这方法直接升级到v4也是可行的。。。</p>
</blockquote>
<p>由于在Strapi v4中REST和GraphQL响应结构的处理方式发生重大变化,意味着原来项目里所有请求和响应方式已经不适用，建议先去看看<a href="https://forum.strapi.io/t/discussion-regarding-the-complex-response-structure-for-rest-graphql-developer-experience/13400">Strapi v4关于REST和GraphQL复杂响应结构的讨论</a>，再衡量是否需要升级。</p>
<p>扁平化REST解决方案：<a href="https://github.com/ComfortablyCoding/strapi-plugin-transformer">strapi-plugin-transformer</a><br>
扁平化GraphQL解决方案：<a href="https://github.com/GavinXue/strapi-study-cases/blob/main/src/plugins/graphql/README.md">Strapi Offcial GraphQL plugin Modify</a></p>
<h2 id="api">转移api相关文件数据</h2>
<p>首先安装个最新版本的strapi看看到底新架构是咋样的</p>
<p><s>复制一个老数据库让strapi v4生成项目时使用</s></p>
<blockquote>
<p>发现strapi4生成数据时会清除现有数据库所有不相关的表，所以其实新建一个空数据库就可以。。。</p>
</blockquote>
<p>启动项目设置好管理员后，直接使用模型构建器新建一个原项目相关字段的model</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="http://lichengwu.net/content/images/2023/03/image.png" class="kg-image"></figure><!--kg-card-begin: markdown--><p>之后查看他生成的相关api文件</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="http://lichengwu.net/content/images/2023/03/image-1.png" class="kg-image"></figure><!--kg-card-begin: markdown--><p>复制一份test目录把里面相关test字眼全部改名为原有的表feedback<br>
再把V3项目文件<code>\api\feedback\models\feedback.settings.json</code>里的<code>attributes</code>对象复制过来</p>]]></description><link>https://lichengwu.net/strapi-v3-to-v4-migration/</link><guid isPermaLink="false">64123b60f0a1230001b772b0</guid><category><![CDATA[strapi]]></category><category><![CDATA[v3-to-v4-migration]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[Navicat]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Tue, 28 Mar 2023 07:04:16 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>由于官方升级文档太一言难尽，而且自己项目基本就只用到GraphQL功能，所以自己尝试适合项目的简单升级迁移方法。</p>
<blockquote>
<p>我是从v3最新版本v3.6.11升级到<s>v4.7.1</s>v4.8.2，理论上v3.x到v3.6期间升级版本之间没有结构性的重大变动用这方法直接升级到v4也是可行的。。。</p>
</blockquote>
<p>由于在Strapi v4中REST和GraphQL响应结构的处理方式发生重大变化,意味着原来项目里所有请求和响应方式已经不适用，建议先去看看<a href="https://forum.strapi.io/t/discussion-regarding-the-complex-response-structure-for-rest-graphql-developer-experience/13400">Strapi v4关于REST和GraphQL复杂响应结构的讨论</a>，再衡量是否需要升级。</p>
<p>扁平化REST解决方案：<a href="https://github.com/ComfortablyCoding/strapi-plugin-transformer">strapi-plugin-transformer</a><br>
扁平化GraphQL解决方案：<a href="https://github.com/GavinXue/strapi-study-cases/blob/main/src/plugins/graphql/README.md">Strapi Offcial GraphQL plugin Modify</a></p>
<h2 id="api">转移api相关文件数据</h2>
<p>首先安装个最新版本的strapi看看到底新架构是咋样的</p>
<p><s>复制一个老数据库让strapi v4生成项目时使用</s></p>
<blockquote>
<p>发现strapi4生成数据时会清除现有数据库所有不相关的表，所以其实新建一个空数据库就可以。。。</p>
</blockquote>
<p>启动项目设置好管理员后，直接使用模型构建器新建一个原项目相关字段的model</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="http://lichengwu.net/content/images/2023/03/image.png" class="kg-image"></figure><!--kg-card-begin: markdown--><p>之后查看他生成的相关api文件</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="http://lichengwu.net/content/images/2023/03/image-1.png" class="kg-image"></figure><!--kg-card-begin: markdown--><p>复制一份test目录把里面相关test字眼全部改名为原有的表feedback<br>
再把V3项目文件<code>\api\feedback\models\feedback.settings.json</code>里的<code>attributes</code>对象复制过来</p>
<blockquote>
<p>这里img字段与v3不同，用回v4的格式。你用到什么格式自己在v4生成对比一下。</p>
</blockquote>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="http://lichengwu.net/content/images/2023/03/image-2.png" class="kg-image"></figure><!--kg-card-begin: markdown--><p>尝试启动项目发现报错</p>
<pre><code>Error: The key of the content-type should be the same as its singularName. Found test and feedback.
</code></pre>
<p>看来没有这么简单嘛，检查Strapi v4生成的数据表发现建model是有数据写入相关字段的，也就是说不能简单地新建几个文件就能自动创建并调用到数据，翻阅了一下相关文档，发现了CLI命令strapi generate</p>
<pre><code>yarn strapi generate
yarn run v1.22.19
$ strapi generate
? Strapi Generators (Use arrow keys)
&gt; api - Generate a basic API
  controller - Generate a controller for an API
  content-type - Generate a content type for an API
  plugin - Generate a basic plugin
  policy - Generate a policy for an API
  middleware - Generate a middleware for an API
  migration - Generate a migration
(Move up and down to reveal more choices)
</code></pre>
<p>初时使用<code>strapi generate api</code>生成v4的model相关文件，再把v3<code>api\feedback\config\routes.json</code>里的routes对象数组复制到v4有注释对应的地方</p>
<pre><code>module.exports = {
  routes: [
    // {
    //  method: 'GET',
    //  path: '/feedback',
    //  handler: 'feedback.exampleAction',
    //  config: {
    //    policies: [],
    //    middlewares: [],
    //  },
    // },
  ],
};
</code></pre>
<p>启动发现报错</p>
<pre><code>error: Error creating endpoint GET /feedbacks: Handler not found &quot;feedback.find&quot;
</code></pre>
<p>google到官方相关<a href="https://github.com/strapi/strapi/issues/11674">issues</a></p>
<p>把<code>routes</code>、<code>controllers</code>、<code>services</code>里文件参照test生成的写法对应复制过来再把test字眼替换成feedback就成功启动了</p>
<blockquote>
<p>如果你生成表后把原来数据备份复盖回生成的表里，记得添加v4新增的两个字段<code>updated_by_id</code>和<code>created_by_id</code>，否则会有以下报错</p>
</blockquote>
<pre><code>error: select `t0`.*, `t0`.`created_by_id`, `t0`.`id`, `t0`.`updated_by_id` from `feedback` as `t0` order by `t0`.`content` ASC limit 10 - ER_BAD_FIELD_ERROR: Unknown column 't0.created_by_id' in 'field list'
Error: ER_BAD_FIELD_ERROR: Unknown column 't0.created_by_id' in 'field list'
</code></pre>
<p>直接使用<code>strapi generate content-type</code>生成modle相关文件</p>
<pre><code>yarn strapi generate
yarn run v1.22.19
$ strapi generate
? Strapi Generators content-type - Generate a content type for an API
? Content type display name feedback
? Content type singular name feedback
? Content type plural name feedbacks
? Please choose the model type Collection Type
? Use draft and publish? No
? Do you want to add attributes? No
You won't be able to manage entries from the admin, you can still add attributes later from the content type builder.
? Where do you want to add this model? Add model to an existing API
? Which API is this for? feedback
? Bootstrap API related files? Yes
√  ++ \api\feedback\content-types\feedback\schema.json
√  ++ \api\feedback\routes\feedback.js
√  ++ \api\feedback\controllers\feedback.js
√  ++ \api\feedback\services\feedback.js
</code></pre>
<h2 id="uploads">转移uploads相关文件数据</h2>
<p>v3、v4的public\uploads都是一样的，复制粘贴过去即可</p>
<p>uploads对应的表</p>
<table>
<thead>
<tr>
<th>v3</th>
<th>v4</th>
</tr>
</thead>
<tbody>
<tr>
<td>upload_file</td>
<td>file</td>
</tr>
<tr>
<td>upload_file_morph</td>
<td>files_related_morphs</td>
</tr>
</tbody>
</table>
<p>使用Navicat导出你v3对应的表数据</p>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card"><img src="http://lichengwu.net/content/images/2023/03/image-3.png" class="kg-image"></figure><!--kg-card-begin: markdown--><p>在v4对应表导入，这里注意改一下从第一个数据行导入</p>
<p><img src="http://lichengwu.net/content/images/2023/03/--------1.jpg" alt="第一个数据行改为1"></p>
<p>对应好导入数据的相关字段并设置好主键，你哪些字段有数据就对应哪些，没有数据可以跳过<br>
<img src="http://lichengwu.net/content/images/2023/03/update_file.jpg" alt="对应字段"></p>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><p>至此其实基本没什么问题可以使用了，如果你还有很多自定义修改需要转移，可以尝试本思路并参考官网文档转移。</p>
<h2 id>结语</h2>
<p>最后我决定放弃升级到最新版本，因为在Strapi v4中，GraphQL模式的定义方式已经发生了变化。也就是说就算把请求数据返回到扁平模式，但以前v3所有定义好的Filters在v4中已经不适用，要么在所有项目上改Filters，要么自己重写v4 GraphQL定义, 尝试了两项修改对于我来说都是极度耗费时间的，并且这种修改对我来说也没什么意义，官方明显表示近期不会有任何v4回到v3格式的任何支持和过渡方案，不过不得不说Strapi v4在很多方面的确比v3优化完善了很多！</p>
<p>PS：严重鄙视Strapi这种对于老用户没有任何过渡方案的升级方式！！！</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Nodejs用户环境对象：CentOS7环境配置dotenv获取.env的process.env.USER失效]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>一直没有单独安装使用过dotenv这个库，一般常用框架都内置集成好了，直接照着样例写.env即可。</p>
<p>最近因开发一个nodejs小应用踩上这个坑，在win7环境调试一切正常，换CentOS7环境出问题。。。</p>
<p>我的.env配置：</p>
<pre><code># env常量
HOST = 192.168.167.167
PORT = 3306
USER = wtf
PASSWORD = wtf2
</code></pre>
<p>在win7环境中成功连接mysql，在CentOS7服务器上一直报</p>
<pre><code>Error: ER_ACCESS_DENIED_ERROR: Access denied for user 'root'@'192.168.168.168' (using password: YES)

# 省略...

code: 'ER_ACCESS_DENIED_ERROR',
errno: 1045,
sqlMessage: &quot;</code></pre>]]></description><link>https://lichengwu.net/centos7-dotenv-process-env-user/</link><guid isPermaLink="false">61efbeac8a650b0001389ffd</guid><category><![CDATA[centos7]]></category><category><![CDATA[dotenv]]></category><category><![CDATA[process.env.USER]]></category><category><![CDATA[.env]]></category><category><![CDATA[nodejs]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Tue, 25 Jan 2022 11:50:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>一直没有单独安装使用过dotenv这个库，一般常用框架都内置集成好了，直接照着样例写.env即可。</p>
<p>最近因开发一个nodejs小应用踩上这个坑，在win7环境调试一切正常，换CentOS7环境出问题。。。</p>
<p>我的.env配置：</p>
<pre><code># env常量
HOST = 192.168.167.167
PORT = 3306
USER = wtf
PASSWORD = wtf2
</code></pre>
<p>在win7环境中成功连接mysql，在CentOS7服务器上一直报</p>
<pre><code>Error: ER_ACCESS_DENIED_ERROR: Access denied for user 'root'@'192.168.168.168' (using password: YES)

# 省略...

code: 'ER_ACCESS_DENIED_ERROR',
errno: 1045,
sqlMessage: &quot;Access denied for user 'root'@'192.168.168.168' (using password: YES)&quot;,
sqlState: '28000',
fatal: true
</code></pre>
<p>尝试不用.env直接在源码上写mysql配置信息成功连接？！怀疑是不是dotenv读取不到配置信息，使用<code>console.log(require('dotenv').config())</code>打印出来的配置也是正确的</p>
<pre><code class="language-javascript">// require('dotenv').config() 返回结果
{
  parsed: {
    HOST: '192.168.167.167',
    PORT: '3306',
    USER: 'wtf',
    PASSWORD: 'wtf2'
  }
}
</code></pre>
<p>初想会不会是常量命名问题？<s>可天真的我认为这个可能性很小</s>，没有尝试继而到google、github上寻找答案。</p>
<p>一轮骚操作下来还是没有获取到可用信息（<em>这问题该怎么描述关键字搜索</em>-_-|||）</p>
<p>一样的配置win7能连上，CentOS7不行？系统环境问题？可打印出来信息又没错鸭？！！</p>
<p>一怒之下把一个个.env里的常量打印出来，结果。。。</p>
<pre><code class="language-javascript">console.log(process.env.HOST)
console.log(process.env.PORT)
console.log(process.env.USER)
console.log(process.env.PASSWORD)

// 输出结果
192.168.167.167
3306
root
wtf2
</code></pre>
<p>怎么<code>process.env.USER</code>变成<code>root</code>了？查<a href="http://nodejs.cn/api/process.html#process_process_env">process.env</a>发现真有一个<code>USER</code>命名的用户环境对象,估计在CentOS7环境里dotenv是复盖不了用户环境对象导致的。。。</p>
<pre><code># 加上DB_前缀解决命名对象冲突问题
DB_HOST = 192.168.167.167
DB_PORT = 3306
DB_USER = wtf
DB_PASSWORD = wtf2
</code></pre>
<p>还是不能太贪图精简，乖乖学各位大佬加个前缀。。。</p>
<h3 id>避坑指南</h3>
<p><strong>.env里常量的命名还是尽量带上阁下独特的前缀，例如：WTF_USER</strong></p>
<p>enjoy life</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[一次假墙攻击引出配置DNSSEC的坑]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h2 id>原由</h2>
<p>最近网站被所谓的烈马团队攻击（伪墙？），指向境外的域名被DNS污染，指向国内的域名被劫持，尝试了什么cloudflare ip轮询（一开始每分钟切换ip时不时还能访问，但很快又被污染，很不稳定），用了什么无视假墙攻击的CDN（没用收费的，价格贼贵而且没试用，估计域名被污染也没什么鸟用，免做冤大头）最后还是没能解决。。。</p>
<p>好吧，近段时间搞到各路站长满城风雨的假墙攻击居然还能弄到我这小站长头上，既然污染无解索性更换域名（俺有权重的域名早已备案回国做301），当然首要解决的就是国内权重域名被劫持问题。</p>
<blockquote>
<p>免费版的DNSPOD安全性也太差了吧，随随便便就能给人劫持！？还是被GFW影响的问题？</p>
</blockquote>
<p>因为一直在用DNSPOD免费的DNS服务，而它的DNSSEC功能是付费才能使用，二话不说搞了款个人专业版，把DNSSEC安排上，先将劫持的问题处理掉，再把被污染的老域名接回cloudflare的NS，还可以用上cloudflare的免费DNSSEC功能。</p>
<blockquote>
<p>DNSSEC不能解污染，仅是cloudflare的NS境外用户能正确解析到才顺便用上，因为当时测试接入 DNSPOD的NS指向CF节点发现境外很多都已经解析不到（现在细想可能是当时启用了DNSSEC功能没配置好）</p>
</blockquote>
<p>新域名刚开始也配置了DNSSEC功能，因为我通过cloudflare partner的CNAME接入自定义CF节点，而cloudflare的DNSSEC功能必须接入它的NS才能使用，所以其实并没有生效。当时国内测试正常我也懒得去把配置好的DNSSEC功能关掉，直到后来发现境外多台主机ping不通新域名和国内被劫持域名。。。</p>
<blockquote>
<p>境外某些测试DNS的网站大部分可以解析到没正确配置DNSSEC的NS记录。。。估计他们不是使用google的DNS</p>
</blockquote>
<p>在境外主机上dig新域名没有NS记录，发现主机使用的DNS是google的<code>8.8.8.</code></p>]]></description><link>https://lichengwu.net/dnspod-dnssec-and-cloudflare-dnssec-precautions/</link><guid isPermaLink="false">60fe435fc74d3d000109704a</guid><category><![CDATA[dnssec]]></category><category><![CDATA[国外ping不通]]></category><category><![CDATA[dnspod]]></category><category><![CDATA[dns]]></category><category><![CDATA[cloudflare]]></category><category><![CDATA[ns]]></category><category><![CDATA[8.8.8.8]]></category><category><![CDATA[8.8.4.4]]></category><category><![CDATA[域名]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Fri, 30 Jul 2021 05:23:11 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id>原由</h2>
<p>最近网站被所谓的烈马团队攻击（伪墙？），指向境外的域名被DNS污染，指向国内的域名被劫持，尝试了什么cloudflare ip轮询（一开始每分钟切换ip时不时还能访问，但很快又被污染，很不稳定），用了什么无视假墙攻击的CDN（没用收费的，价格贼贵而且没试用，估计域名被污染也没什么鸟用，免做冤大头）最后还是没能解决。。。</p>
<p>好吧，近段时间搞到各路站长满城风雨的假墙攻击居然还能弄到我这小站长头上，既然污染无解索性更换域名（俺有权重的域名早已备案回国做301），当然首要解决的就是国内权重域名被劫持问题。</p>
<blockquote>
<p>免费版的DNSPOD安全性也太差了吧，随随便便就能给人劫持！？还是被GFW影响的问题？</p>
</blockquote>
<p>因为一直在用DNSPOD免费的DNS服务，而它的DNSSEC功能是付费才能使用，二话不说搞了款个人专业版，把DNSSEC安排上，先将劫持的问题处理掉，再把被污染的老域名接回cloudflare的NS，还可以用上cloudflare的免费DNSSEC功能。</p>
<blockquote>
<p>DNSSEC不能解污染，仅是cloudflare的NS境外用户能正确解析到才顺便用上，因为当时测试接入 DNSPOD的NS指向CF节点发现境外很多都已经解析不到（现在细想可能是当时启用了DNSSEC功能没配置好）</p>
</blockquote>
<p>新域名刚开始也配置了DNSSEC功能，因为我通过cloudflare partner的CNAME接入自定义CF节点，而cloudflare的DNSSEC功能必须接入它的NS才能使用，所以其实并没有生效。当时国内测试正常我也懒得去把配置好的DNSSEC功能关掉，直到后来发现境外多台主机ping不通新域名和国内被劫持域名。。。</p>
<blockquote>
<p>境外某些测试DNS的网站大部分可以解析到没正确配置DNSSEC的NS记录。。。估计他们不是使用google的DNS</p>
</blockquote>
<p>在境外主机上dig新域名没有NS记录，发现主机使用的DNS是google的<code>8.8.8.8</code>；<br>
在本地使用<code>nslookup www.xxx.com 8.8.8.8</code>发现也没有NS记录，但国内常用的DNS例如<code>114.114.114.114</code> <code>119.29.29.29</code> <code>223.5.5.5</code> 都能正确识别出NS记录；</p>
<p>Google搜索无果后国外主机尝试ping接入了cloudflare NS的被污染老域名居然能通（之前测试打开了DNSSEC功能但使用DNSPOD指向CF节点也是ping不通的），于是开始怀疑是否DNSSEC的问题？立马把新域名没用上的DNSSEC功能关闭，不到一会就ping通了，dig也能解析到NS记录。到<a href="https://dnsviz.net/">dnsviz.net</a>网站检查发现原本配置好DNSSEC的国内域名出现问题（刚开始检测没问题的，不知道咋弄的），到DNSPOD关闭DNSSEC功能并到域名商DNSSEC设置里删除原来的配置，重新开启并配置就好了。。。</p>
<h2 id>总结</h2>
<ul>
<li>域名DNSSEC功能打开后没有用或没配置一定要关闭掉，域名配置过也请把DNSSEC记录删除掉，否则部分国外DNS解析不到；</li>
<li>域名开启了DNSSEC功能一定要到<a href="https://dnsviz.net/">dnsviz.net</a>检测是否配置成功；</li>
</ul>
<h2 id>一句话</h2>
<p>域名的DNSSEC功能不需要就别打开或配置！！！</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[chrome cloudflare 520 error 解决办法]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>自从上了cloudflare cdn后，时不时访问网站都会报520 error，因为网站一直被cc攻击，所以一直都认为是被cc攻击导致的，思路都是通过优化调整nginx的配置，但一直得不到满意的效果，直到最近操作后台频繁出现520 error，才花了点时间研究了一下。。。</p>
</blockquote>
<h3 id>解决流程</h3>
<ol>
<li>首先到官方帮助<a href="https://support.cloudflare.com/hc/zh-cn/articles/115003011431-Cloudflare-5XX-%E9%94%99%E8%AF%AF%E6%95%85%E9%9A%9C%E6%8E%92%E9%99%A4#520error">Cloudflare 5XX 错误故障排除<br>
</a>了解和排查520相关原因（官方概况得比较全面且复杂，排查了很久都得不到解决）</li>
<li>用chrome直接访问源站后台，尝试复现问题，但发现一切正常，故排除Nginx的配置问题</li>
<li>尝试在另外一台电脑另一个网络（电信）用firefox访问带cdn的后台，发现没有问题，故怀疑是否cloudflare节点原因</li>
<li>更换cloudflare节点，用chrome本地移动网络和电信网络代理访问带cdn的后台，均发现问题依旧，故排除cloudflare节点问题</li>
<li>尝试本地用firefox访问带cdn的后台，竟然没有问题，故怀疑问题出在chrome上</li>
<li>搜索相关资料发现<a href="https://community.cloudflare.com/t/520-error-cache-clearing/213509">520 Error Cache Clearing</a>，尝试在chrome清空该网站cookie，问题解决</li>
</ol>
<!--kg-card-end: markdown--><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2020/11/image.png" class="kg-image"><figcaption>Chrome设置 -&gt; Cookie及其他网站数据</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2020/11/image-1.png" class="kg-image"><figcaption>查看所有Cookie和网站数据</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2020/11/image-2.png" class="kg-image"><figcaption>删除相关网站Cookie</figcaption></figure>]]></description><link>https://lichengwu.net/chrome-cloudflare-520-error/</link><guid isPermaLink="false">5faa3cc3d50b13000114a8a0</guid><category><![CDATA[chrome]]></category><category><![CDATA[cloudflare 520 error]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Tue, 10 Nov 2020 08:35:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>自从上了cloudflare cdn后，时不时访问网站都会报520 error，因为网站一直被cc攻击，所以一直都认为是被cc攻击导致的，思路都是通过优化调整nginx的配置，但一直得不到满意的效果，直到最近操作后台频繁出现520 error，才花了点时间研究了一下。。。</p>
</blockquote>
<h3 id>解决流程</h3>
<ol>
<li>首先到官方帮助<a href="https://support.cloudflare.com/hc/zh-cn/articles/115003011431-Cloudflare-5XX-%E9%94%99%E8%AF%AF%E6%95%85%E9%9A%9C%E6%8E%92%E9%99%A4#520error">Cloudflare 5XX 错误故障排除<br>
</a>了解和排查520相关原因（官方概况得比较全面且复杂，排查了很久都得不到解决）</li>
<li>用chrome直接访问源站后台，尝试复现问题，但发现一切正常，故排除Nginx的配置问题</li>
<li>尝试在另外一台电脑另一个网络（电信）用firefox访问带cdn的后台，发现没有问题，故怀疑是否cloudflare节点原因</li>
<li>更换cloudflare节点，用chrome本地移动网络和电信网络代理访问带cdn的后台，均发现问题依旧，故排除cloudflare节点问题</li>
<li>尝试本地用firefox访问带cdn的后台，竟然没有问题，故怀疑问题出在chrome上</li>
<li>搜索相关资料发现<a href="https://community.cloudflare.com/t/520-error-cache-clearing/213509">520 Error Cache Clearing</a>，尝试在chrome清空该网站cookie，问题解决</li>
</ol>
<!--kg-card-end: markdown--><p></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2020/11/image.png" class="kg-image"><figcaption>Chrome设置 -&gt; Cookie及其他网站数据</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2020/11/image-1.png" class="kg-image"><figcaption>查看所有Cookie和网站数据</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2020/11/image-2.png" class="kg-image"><figcaption>删除相关网站Cookie</figcaption></figure>]]></content:encoded></item><item><title><![CDATA[uni-app配置使用GraphQL]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>dcloud官方暂时没有关于如何支持GraphQL的说明，不过uni-app配置GraphQL还是挺简单的，但不熟悉uni-app和GraphQL的童鞋配置起来还是会比较迷茫，到处是坑。。。</p>
<p>其实早已经有热心的童鞋提拱支持uni-app的GraphQL client，我看了一下他github上的源码，发现是移植自国外一位GraphQL大神的库，而且该库相关说明和用例比较缺乏，说白了就是生态支持不好，遇到问题很难找到解决方法，而且该童鞋也不维护了，很多时候还得自己看源码慢慢调试摸索，我用来开发了一个项目，涉及上传功能的时候弄到我想哭。。。</p>
<h2 id="axiosgraphqlapi">使用Axios请求GraphQL API</h2>
<p>提到GraphQL client，了解GraphQL的童鞋可能第一反应想到的就是Apollo，其实如果你无需用到Apollo生态及其功能特性，即不必使用此类框架，你可以使用任何你想要的库。</p>
<p>GraphQL本身并不关心网络层，所以你完全可以使用普通的HTTP方法带上具有GraphQL查询和修改的结构内容对其进行操作。</p>
<blockquote>
<p>有时候引入框架意味着对现有架构进行大量修改，以至于很多人不敢在老项目中使用或直接放弃GraphQL，对大多数前端开发者来说，可能所有http请求仅用Axios就能搞定是最理想的状态。。。</p>
</blockquote>
<p>所以我们可以用Axios这样请求GraphQL API：</p>
<pre><code class="language-js">import axios from 'axios'

axios.post(graphqlURL, {
query: `
    query albums {
      albums(limit: ${this.limit) {
          title
          content
          images
      }
    }
`}).then(res</code></pre>]]></description><link>https://lichengwu.net/uni-app-graphql/</link><guid isPermaLink="false">5ebaf4020ae61a000171a1ce</guid><category><![CDATA[uni-app]]></category><category><![CDATA[GraphQL]]></category><category><![CDATA[axios]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Wed, 13 May 2020 12:03:31 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>dcloud官方暂时没有关于如何支持GraphQL的说明，不过uni-app配置GraphQL还是挺简单的，但不熟悉uni-app和GraphQL的童鞋配置起来还是会比较迷茫，到处是坑。。。</p>
<p>其实早已经有热心的童鞋提拱支持uni-app的GraphQL client，我看了一下他github上的源码，发现是移植自国外一位GraphQL大神的库，而且该库相关说明和用例比较缺乏，说白了就是生态支持不好，遇到问题很难找到解决方法，而且该童鞋也不维护了，很多时候还得自己看源码慢慢调试摸索，我用来开发了一个项目，涉及上传功能的时候弄到我想哭。。。</p>
<h2 id="axiosgraphqlapi">使用Axios请求GraphQL API</h2>
<p>提到GraphQL client，了解GraphQL的童鞋可能第一反应想到的就是Apollo，其实如果你无需用到Apollo生态及其功能特性，即不必使用此类框架，你可以使用任何你想要的库。</p>
<p>GraphQL本身并不关心网络层，所以你完全可以使用普通的HTTP方法带上具有GraphQL查询和修改的结构内容对其进行操作。</p>
<blockquote>
<p>有时候引入框架意味着对现有架构进行大量修改，以至于很多人不敢在老项目中使用或直接放弃GraphQL，对大多数前端开发者来说，可能所有http请求仅用Axios就能搞定是最理想的状态。。。</p>
</blockquote>
<p>所以我们可以用Axios这样请求GraphQL API：</p>
<pre><code class="language-js">import axios from 'axios'

axios.post(graphqlURL, {
query: `
    query albums {
      albums(limit: ${this.limit) {
          title
          content
          images
      }
    }
`}).then(res =&gt; {
    console.log(res)
}).catch(err =&gt; {
    console.log(err)
})
</code></pre>
<h2 id="graphqltagandprint">graphql-tag and print</h2>
<p><a href="https://github.com/apollographql/graphql-tag">graphql-tag</a>用来把string转化成 GraphQL的AST。既然在客户端发请求时仍然使用string，为什么需要客户端转成AST呢？这有几个原因：</p>
<ul>
<li>编译成 AST 可以在编译时检查确保 query 的合法性 (比如查询了不存在的字段)</li>
<li>可以按照特定条件对多个 query 进行合并，多个请求合并为同一个请求</li>
<li>可以按照客户端缓存对某些字段进行过滤 (skip)，避免冗余查询</li>
<li>... 诸多好处</li>
</ul>
<p>在服务器端也有诸多好处，如：</p>
<ul>
<li>解析出来客户端请求的 field，与数据库一对比，按需请求数据库字段</li>
<li>添加新的 directives</li>
<li>...</li>
</ul>
<p>而print的作用是：Converts an AST into a string, using one set of reasonable formatting rules</p>
<pre><code class="language-js">import axios from 'axios'
import gql from 'graphql-tag'
import { print } from 'graphql'

const LOGIN = gql`mutation login($identifier:String!, $password:String!){
                    login(input:{
                        identifier: $identifier
                        password: $password
                    }){
                        jwt
                        user {
                            username
                        }
                    }
                }`

axios.post(graphqlURL, {
    query: print(LOGIN),
    variables: {
        identifier: this.email,
        password: this.password
    }
})
.then(res =&gt; {
    console.log(res)
})
.catch(err =&gt; {
    console.log(err)
})
</code></pre>
<h2 id="uniappgraphqlapi">让uni-app支持请求GraphQL API</h2>
<p>好吧，说了那么多该进主题了，下面我们开始配置uni-app。</p>
<p>uni-app里直接使用Axios在App端和小程序端会报错，得自己定义适配，可参考<br>
<a href="https://www.cnblogs.com/merryan-share/p/12418450.html">在uniapp设计的APP中引入axios，支持cookie（真机亲测可行）</a></p>
<p>我在这里就不折腾了，直接在uni-app插件市场下载仿Axios的库<a href="https://ext.dcloud.net.cn/plugin?id=392">luch-request</a></p>
<pre><code>// 如果你的项目还没有package.json文件
// npm init -y

// 安装
npm install graphql graphql-tag
</code></pre>
<pre><code class="language-js">// main.js

import Request from '@/utils/luch-request/index.js'
import gql from 'graphql-tag'
import { print } from 'graphql'

Vue.prototype.$http = new Request()
Vue.prototype.$gql = gql
Vue.prototype.$print = print
</code></pre>
<p>我们来测试一下请求是否能成功</p>
<pre><code class="language-js">const LOGIN = this.$gql`mutation login($identifier:String!, $password:String!){
                    login(input:{
                        identifier: $identifier
                        password: $password
                    }){
                        jwt
                        user {
                            username
                        }
                    }
                }`

this.$http.post(graphqlURL, {
    query: this.$print(LOGIN),
    variables: {
        identifier: this.email,
        password: this.password
    }
})
.then(res =&gt; {
    console.log(res)
})
.catch(err =&gt; {
    console.log(err)
})
</code></pre>
<p>发现graphql报错</p>
<pre><code>Uncaught ReferenceError: require is not defined
    at eval (parser.mjs?2604:1)
    at Module.../../../../project/uni-app-graphql/node_modules/graphql/language/parser.mjs (chunk-vendors.js:34)
    at __webpack_require__ (index.js:787)
    at fn (index.js:150)
    at eval (index.js?f743:1)
    at Object.../../../../project/uni-app-graphql/node_modules/graphql-tag/src/index.js (chunk-vendors.js:10)
    at __webpack_require__ (index.js:787)
    at fn (index.js:150)
    at eval (main.js?3d9e:4)
    at Object.../../../../project/uni-app-graphql/main.js (index.js:985)
</code></pre>
<p>不熟悉webpack和vue.config.js配置的估计到这里够呛。。。</p>
<p>google一下说是要让webpack支持mjs后缀，在vue.config.js中尝试了webpack的配置方法还是不行，后来才发现vue有自己的一套<a href="https://cli.vuejs.org/zh/config/#vue-config-js">vue config命令</a>。。。</p>
<p>根目录新建vue.config.js文件并添加以下代码</p>
<pre><code>module.exports = {
    chainWebpack: (config) =&gt; {
        // GraphQL Loader
        config.module // optional
            .rule('graphql')
            .test(/\.graphql$/)
            .use('graphql-tag/loader')
            .loader('graphql-tag/loader')
            .end()

        config.module
            .rule('mjs')
            .test(/\.mjs$/)
            .include.add(/node_modules/)
            .end()
            .type('javascript/auto')
            .end()

        config.resolve.extensions
            .add('.mjs')
            .add('.gql')
            .add('.graphql')
            .end()
    }
}
</code></pre>
<p>好了，现在你可以愉快地使用Axios一边请求GraphQL API，一边请求RESTful API。。。</p>
<p>enjoy life</p>
<p>参考：<br>
<a href="https://github.com/Pines-Cheng/blog/issues/79">https://github.com/Pines-Cheng/blog/issues/79</a><br>
<a href="https://github.com/vuejs/vue-cli/issues/1637">https://github.com/vuejs/vue-cli/issues/1637</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[宝塔极速安装Nginx环境下开启云锁Nginx自编译防护]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>近段时间站点被各类攻击频繁骚扰，虽已接入cloudflare并添加了相关cc策略，但不直接启用5秒盾感觉效果不太理想（可能是我配的策略还不够好吧。。），启用5秒盾还得放行搜索引擎爬虫ip，虽然cloudflare也有提拱大部分常见搜索引擎机器人规则，但首次访问或隔段时间访问总要等待5秒感觉体验非常不好。。。</p>
<p>一直想试用云锁的敏感词过滤功能，但对Nginx的操作感觉十分麻烦（弄懂后还满简单。。），固之前在服务器上安装了云锁之后就不了了之。。。但碍于最近的频频cc攻击，急需稳固且强大的Nginx防cc功能，道听途说云锁的抗CC功能不错，查阅了云锁Github上的<a href="https://github.com/yunsuo-open/nginx-plugin">Nginx模块</a>发现最近还在更新，好吧于是做足功课直接拿下，现分享出来希望能为诸位节省点宝贵时间。。。</p>
<p>网上能搜索到的教程基本上都要求在编译安装的Nginx环境下添加云锁Nginx模块，其实极速安装和编译安装<strong>就只差了个src目录</strong>，src目录其实就是Nginx的源码目录，极速安装下Nginx目录里是没有src目录的，清楚这点就简单了，直接下载个Nginx源码包基本就跟编译安装一样（宝塔编译安装还自带了一些模块，我们要自己加进去）</p>
<blockquote>
<p>首先你得注册并安装云锁，google教程很多在这里就不展开了。。。</p>
</blockquote>
<h2 id="nginx">下载Nginx源码包</h2>
<p>以Nginx1.15.10为例,进入宝塔nginx目录并下载Nginx源码包，解压源码包并重命名为src</p>
<blockquote>
<p>如果你还没有安装nginx，直接编译安装nginx就完事了，这里以极速安装环境下操作</p>
</blockquote>
<pre><code>cd /www/server/nginx/
wget https://nginx.org/download/nginx-1.15.</code></pre>]]></description><link>https://lichengwu.net/baota-install-yunsuo-nginx-plugin/</link><guid isPermaLink="false">5e58de53e30b4d00015c3d85</guid><category><![CDATA[Nginx]]></category><category><![CDATA[宝塔]]></category><category><![CDATA[云锁]]></category><category><![CDATA[极速安装]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Sat, 29 Feb 2020 12:07:42 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>近段时间站点被各类攻击频繁骚扰，虽已接入cloudflare并添加了相关cc策略，但不直接启用5秒盾感觉效果不太理想（可能是我配的策略还不够好吧。。），启用5秒盾还得放行搜索引擎爬虫ip，虽然cloudflare也有提拱大部分常见搜索引擎机器人规则，但首次访问或隔段时间访问总要等待5秒感觉体验非常不好。。。</p>
<p>一直想试用云锁的敏感词过滤功能，但对Nginx的操作感觉十分麻烦（弄懂后还满简单。。），固之前在服务器上安装了云锁之后就不了了之。。。但碍于最近的频频cc攻击，急需稳固且强大的Nginx防cc功能，道听途说云锁的抗CC功能不错，查阅了云锁Github上的<a href="https://github.com/yunsuo-open/nginx-plugin">Nginx模块</a>发现最近还在更新，好吧于是做足功课直接拿下，现分享出来希望能为诸位节省点宝贵时间。。。</p>
<p>网上能搜索到的教程基本上都要求在编译安装的Nginx环境下添加云锁Nginx模块，其实极速安装和编译安装<strong>就只差了个src目录</strong>，src目录其实就是Nginx的源码目录，极速安装下Nginx目录里是没有src目录的，清楚这点就简单了，直接下载个Nginx源码包基本就跟编译安装一样（宝塔编译安装还自带了一些模块，我们要自己加进去）</p>
<blockquote>
<p>首先你得注册并安装云锁，google教程很多在这里就不展开了。。。</p>
</blockquote>
<h2 id="nginx">下载Nginx源码包</h2>
<p>以Nginx1.15.10为例,进入宝塔nginx目录并下载Nginx源码包，解压源码包并重命名为src</p>
<blockquote>
<p>如果你还没有安装nginx，直接编译安装nginx就完事了，这里以极速安装环境下操作</p>
</blockquote>
<pre><code>cd /www/server/nginx/
wget https://nginx.org/download/nginx-1.15.10.tar.gz
tar xzvf nginx-1.15.10.tar.gz
mv nginx-1.15.10 src
</code></pre>
<h2 id="nginx">下载云锁Nginx模块</h2>
<p>进入src目录，下载云锁Nginx模块并解压</p>
<pre><code>cd /www/server/nginx/src
wget https://codeload.github.com/yunsuo-open/nginx-plugin/zip/master -O nginx-plugin-master.zip
unzip nginx-plugin-master.zip
</code></pre>
<h2 id="nginx">查看宝塔Nginx原有的模块</h2>
<pre><code>nginx -V 
</code></pre>
<p><img src="http://lichengwu.net/content/images/2020/02/image-1.png" alt></p>
<p>把 ./configure arguents：之后的内容复制到记事本备用</p>
<h2 id="nginx">恢复宝塔原有的Nginx模块</h2>
<p>用你能想到的办法把宝塔原有的Nginx模块移进src目录，你可以在其它服务器或本地安装宝塔并编译安装Nginx，把相关的8个模块打包进来，其它版本没有测试，反正大同小异，如果别的版本./configure的时候报缺少相关模块，同样把缺少的模块移进来就完事啦。。。</p>
<p><img src="http://lichengwu.net/content/images/2020/02/image.png" alt></p>
<ul>
<li>lua_nginx_module</li>
<li>nginx-dav-ext-module</li>
<li>nginx-http-concat</li>
<li>nginx-sticky-module</li>
<li>ngx_cache_purge</li>
<li>ngx_devel_kit</li>
<li>openssl</li>
<li>pcre-8.43</li>
</ul>
<h2 id="nginx">添加云锁Nginx模块</h2>
<p>./configure {刚才复制的内容} --add-module=/www/server/nginx/src/nginx-plugin-master</p>
<pre><code>./configure  --user=www --group=www --prefix=/www/server/nginx --with-openssl=/www/server/nginx/src/openssl --add-module=/www/server/nginx/src/ngx_devel_kit --add-module=/www/server/nginx/src/lua_nginx_module --add-module=/www/server/nginx/src/ngx_cache_purge --add-module=/www/server/nginx/src/nginx-sticky-module --with-http_stub_status_module --with-http_ssl_module --with-http_v2_module --with-http_image_filter_module --with-http_gzip_static_module --with-http_gunzip_module --with-stream --with-stream_ssl_module --with-ipv6 --with-http_sub_module --with-http_flv_module --with-http_addition_module --with-http_realip_module --with-http_mp4_module --with-ld-opt=-Wl,-E --with-openssl-opt='enable-tls1_3 enable-weak-ssl-ciphers' --with-ld-opt=-ljemalloc --add-module=/www/server/nginx/src/nginx-plugin-master
</code></pre>
<blockquote>
<p>成功后报 ./configure: warning: the &quot;--with-ipv6&quot; option is deprecated 正常，别慌！</p>
</blockquote>
<h2 id="nginx">编译Nginx</h2>
<p>等待添加模块命令结束，输入编译命令</p>
<pre><code>make
</code></pre>
<p>喝杯茶抽根烟静待编译结束。。。</p>
<h2 id="nginx">重命名并备份原来的Nginx</h2>
<blockquote>
<p>不会影响你正在运行的Nginx服务，don't worry</p>
</blockquote>
<pre><code>mv /www/server/nginx/sbin/nginx /www/server/nginx/sbin/nginx.bak
</code></pre>
<h2 id="nginxnginx">复制编译后的Nginx文件到宝塔Nginx目录并添加权限</h2>
<pre><code>cp /www/server/nginx/src/objs/nginx /www/server/nginx/sbin/
chmod 755 /www/server/nginx/sbin/nginx
</code></pre>
<h2 id>重启并测试</h2>
<p>重启Nginx服务</p>
<pre><code>service nginx restart
</code></pre>
<p>查看云锁PC客户端自编译是否成功点亮，没意外你的云锁Nginx自编译图标应该就亮起来了。。。</p>
<p><img src="http://lichengwu.net/content/images/2020/02/image-2.png" alt></p>
<p>在你的域名后加上/?order%20by，如果被拦截。。恭喜你。。成功上锁。。。</p>
<p><img src="http://lichengwu.net/content/images/2020/02/image-3.png" alt></p>
<h2 id="cc">调整防御CC相关参数</h2>
<p>设置成每60秒允许请求10次足矣（开启中级防护要注意程序是否有拦截非法参数功能，否则程序拦截了云锁的url参数会跳转失败）这里因为攻击来得猛我调得猛：）</p>
<p><img src="http://lichengwu.net/content/images/2020/02/image-4.png" alt></p>
<p>频频拦截，酸爽！</p>
<p><img src="http://lichengwu.net/content/images/2020/02/image-5.png" alt></p>
<p>enjoy life</p>
<p>参考：<br>
<a href="https://www.vpskp.com/post/3153.html">https://www.vpskp.com/post/3153.html</a><br>
<a href="https://www.vpskp.com/post/2164.html">https://www.vpskp.com/post/2164.html</a><br>
<a href="https://www.madapang.com/technology/btyunsuo.html">https://www.madapang.com/technology/btyunsuo.html</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[uni-app h5发行生产环境自动去除console.log和debugger]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>uni-app根目录默认没有<a href="https://uniapp.dcloud.io/collocation/vue-config">vue.config.js</a>，新建并添加以下代码</p>
<pre><code>module.exports = {
    productionSourceMap: false, // 生产打包时不输出map文件，增加打包速度
    configureWebpack: config =&gt; {
        if (process.env.NODE_ENV === 'production') {
            config.optimization.minimizer[0].options.terserOptions.compress.warnings = false
            config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
            config.optimization.minimizer[0].options.terserOptions.compress.drop_debugger = true
            config.</code></pre>]]></description><link>https://lichengwu.net/uni-app-h5-production-remove-console-and-debugger/</link><guid isPermaLink="false">5e3fcaec221eb40001ff97b4</guid><category><![CDATA[uni-app]]></category><category><![CDATA[console.log]]></category><category><![CDATA[debugger]]></category><category><![CDATA[vue]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Sun, 09 Feb 2020 09:20:09 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>uni-app根目录默认没有<a href="https://uniapp.dcloud.io/collocation/vue-config">vue.config.js</a>，新建并添加以下代码</p>
<pre><code>module.exports = {
    productionSourceMap: false, // 生产打包时不输出map文件，增加打包速度
    configureWebpack: config =&gt; {
        if (process.env.NODE_ENV === 'production') {
            config.optimization.minimizer[0].options.terserOptions.compress.warnings = false
            config.optimization.minimizer[0].options.terserOptions.compress.drop_console = true
            config.optimization.minimizer[0].options.terserOptions.compress.drop_debugger = true
            config.optimization.minimizer[0].options.terserOptions.compress.pure_funcs = ['console.log']
        }
    }
}
</code></pre>
<p>enjoy life</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[批量去除数据库中的&#65279;]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>使用GraphQL Playground查询数据时发现某些字段多了个红点?</p>
<p><img src="http://lichengwu.net/content/images/2019/12/image.png" alt="﻿"></p>
<p>一番操作下来发现前台和后台显示又正常，起初没什么问题也懒得管，直到用GraphQL筛选数据时 <code>d_area: &quot;大陆&quot;</code> 发现带红点的记录都查询不出来（老的那套php写的后台管理系统能筛选！！！）用Chrome DevTools查看HTML源码发现字符被渲染了出来 <code>&amp;#65279;大陆</code>，google了一下都说是UTF-8保存时带BOM引起的，因为老系统是把地区信息保存到txt文件，估计就是这个txt文件的编码问题，用vscode打开这个txt果然显示UTF-8 with BOM</p>
<p><img src="http://lichengwu.net/content/images/2019/12/image-2.png" alt="UTF-8 with BOM"></p>
<p>把他改为UTF-8编码保存就好了，接下来再把原来写进Mysql里的地区数据批量改过来。</p>
<p>一开始我直接替换 <code>&amp;#65279;</code> 字符发现找不到</p>
<pre><code class="language-sql">UPDATE `vod` SET `d_area`= REPLACE(`d_area`, '&amp;#65279;', '')
</code></pre>
<p>之后干脆直接复制GraphQL Playground里的 <code>﻿</code> 字符替换就成功了</p>
<blockquote>
<p>这个空字符这里显示不出来，直接复制就好</p>
</blockquote>
<pre><code class="language-sql">UPDATE `vod` SET</code></pre>]]></description><link>https://lichengwu.net/65279/</link><guid isPermaLink="false">5e064f36221eb40001ff9696</guid><category><![CDATA[GraphQL]]></category><category><![CDATA[&#65279;]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Fri, 27 Dec 2019 19:46:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>使用GraphQL Playground查询数据时发现某些字段多了个红点?</p>
<p><img src="http://lichengwu.net/content/images/2019/12/image.png" alt="﻿"></p>
<p>一番操作下来发现前台和后台显示又正常，起初没什么问题也懒得管，直到用GraphQL筛选数据时 <code>d_area: &quot;大陆&quot;</code> 发现带红点的记录都查询不出来（老的那套php写的后台管理系统能筛选！！！）用Chrome DevTools查看HTML源码发现字符被渲染了出来 <code>&amp;#65279;大陆</code>，google了一下都说是UTF-8保存时带BOM引起的，因为老系统是把地区信息保存到txt文件，估计就是这个txt文件的编码问题，用vscode打开这个txt果然显示UTF-8 with BOM</p>
<p><img src="http://lichengwu.net/content/images/2019/12/image-2.png" alt="UTF-8 with BOM"></p>
<p>把他改为UTF-8编码保存就好了，接下来再把原来写进Mysql里的地区数据批量改过来。</p>
<p>一开始我直接替换 <code>&amp;#65279;</code> 字符发现找不到</p>
<pre><code class="language-sql">UPDATE `vod` SET `d_area`= REPLACE(`d_area`, '&amp;#65279;', '')
</code></pre>
<p>之后干脆直接复制GraphQL Playground里的 <code>﻿</code> 字符替换就成功了</p>
<blockquote>
<p>这个空字符这里显示不出来，直接复制就好</p>
</blockquote>
<pre><code class="language-sql">UPDATE `vod` SET `d_area`= REPLACE(`d_area`, '﻿', '')
</code></pre>
<p>enjoy life</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[uni-app报错：undefined is not an object (evaluating 'obj[key]');]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>开发Android报错，H5没问题，IOS和各小程序没测，根据<a href="https://ask.dcloud.net.cn/question/79868">这位兄弟的反馈</a>，估计只在APP里报这错。。。</p>
<p>我是在嵌套的v-for循环绑定tap事件传参报错，不嵌套的v-for绑定tap事件传参没问题。</p>
<p>解决办法：<strong>改用navigator组件来传参</strong></p>
<h2 id="tap">tap事件传参报错代码</h2>
<pre><code class="language-html">&lt;swiper-item v-for=&quot;(item, tabbarIdx) in tabbar&quot; :key=&quot;tabbarIdx&quot;&gt;
  &lt;scroll-view scroll-y class=&quot;scoll-y&quot; @scrolltolower=&quot;onBottom&quot;&gt;
    &lt;view class=&quot;vod-list&quot;&gt;
      &lt;view class=&quot;vod-list-item&quot;</code></pre>]]></description><link>https://lichengwu.net/uni-app-error-undefined-is-not-an-object-evaluating-obj-key/</link><guid isPermaLink="false">5de586c1221eb40001ff95e0</guid><category><![CDATA[uni-app]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Mon, 02 Dec 2019 22:27:23 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>开发Android报错，H5没问题，IOS和各小程序没测，根据<a href="https://ask.dcloud.net.cn/question/79868">这位兄弟的反馈</a>，估计只在APP里报这错。。。</p>
<p>我是在嵌套的v-for循环绑定tap事件传参报错，不嵌套的v-for绑定tap事件传参没问题。</p>
<p>解决办法：<strong>改用navigator组件来传参</strong></p>
<h2 id="tap">tap事件传参报错代码</h2>
<pre><code class="language-html">&lt;swiper-item v-for=&quot;(item, tabbarIdx) in tabbar&quot; :key=&quot;tabbarIdx&quot;&gt;
  &lt;scroll-view scroll-y class=&quot;scoll-y&quot; @scrolltolower=&quot;onBottom&quot;&gt;
    &lt;view class=&quot;vod-list&quot;&gt;
      &lt;view class=&quot;vod-list-item&quot; v-for=&quot;(vod, index) in vods.vodlist[tabbarIdx + 1].data&quot; :key=&quot;index&quot; @tap=&quot;vodPlay(vod.id)&quot;&gt;
        &lt;view class=&quot;vod-list-box&quot;&gt;
          &lt;image mode=&quot;aspectFill&quot; lazy-load=&quot;true&quot; class=&quot;vod-list-img&quot; :src=&quot;`https://localhost/${vod.d_pic}`&quot;&gt;&lt;/image&gt;
        &lt;/view&gt;
        &lt;view class=&quot;vod-list-title&quot;&gt;{{ vod.d_name }}&lt;/view&gt;&lt;/view&gt;
    &lt;/view&gt;
  &lt;/scroll-view&gt;
&lt;/swiper-item&gt;
</code></pre>
<h2 id="navigator">navigator传参正确代码</h2>
<pre><code class="language-html">&lt;swiper-item v-for=&quot;(item, tabbarIdx) in tabbar&quot; :key=&quot;tabbarIdx&quot;&gt;
  &lt;scroll-view scroll-y class=&quot;scoll-y&quot; @scrolltolower=&quot;onBottom&quot;&gt;
    &lt;view class=&quot;vod-list&quot;&gt;
      &lt;view class=&quot;vod-list-item&quot; v-for=&quot;(vod, index) in vods.vodlist[tabbarIdx + 1].data&quot; :key=&quot;index&quot;&gt;
        &lt;navigator :url=&quot;`../vodplay/vodplay?id=${vod.id}`&quot;&gt;
          &lt;view class=&quot;vod-list-box&quot;&gt;
            &lt;image mode=&quot;aspectFill&quot; lazy-load=&quot;true&quot; class=&quot;vod-list-img&quot; :src=&quot;`https://localhost/${vod.d_pic}`&quot;&gt;&lt;/image&gt;
          &lt;/view&gt;
          &lt;view class=&quot;vod-list-title&quot;&gt;{{ vod.d_name }}&lt;/view&gt;
        &lt;/navigator&gt;
      &lt;/view&gt;
    &lt;/view&gt;
  &lt;/scroll-view&gt;
&lt;/swiper-item&gt;
</code></pre>
<p>enjoy life</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Prisma连接到现有MySQL的坑]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>按官网教程执行完<code>docker-compose up -d</code>，发现 <a href="http://localhost:4466/">http://localhost:4466/</a> 起不来</p>
<p>执行 <code>docker logs --since 30m CONTAINER_ID</code> 查看容器日志</p>
<p>发现以下报错：</p>
<pre><code>Unable to load Prisma config: com.prisma.config.InvalidConfiguration: Only Postgres connectors specify a schema. If they do they also need to specify a database. Other connectors only specify a database.
</code></pre>
<p>官方默认生成的docker-compose.</p>]]></description><link>https://lichengwu.net/prisma-mysql/</link><guid isPermaLink="false">5dbfeed38dfa540001cbf0cc</guid><category><![CDATA[prisma]]></category><category><![CDATA[mysql]]></category><category><![CDATA[docker]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Mon, 04 Nov 2019 11:00:47 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>按官网教程执行完<code>docker-compose up -d</code>，发现 <a href="http://localhost:4466/">http://localhost:4466/</a> 起不来</p>
<p>执行 <code>docker logs --since 30m CONTAINER_ID</code> 查看容器日志</p>
<p>发现以下报错：</p>
<pre><code>Unable to load Prisma config: com.prisma.config.InvalidConfiguration: Only Postgres connectors specify a schema. If they do they also need to specify a database. Other connectors only specify a database.
</code></pre>
<p>官方默认生成的docker-compose.yml配置的是schema，由于MySql没有schema，把schema改成database</p>
<pre><code>version: '3'
services:
  prisma:
    image: prismagraphql/prisma:1.34
    restart: always
    ports:
    - &quot;4466:4466&quot;
    environment:
      PRISMA_CONFIG: |
        port: 4466
        # uncomment the next line and provide the env var PRISMA_MANAGEMENT_API_SECRET=my-secret to activate cluster security
        # managementApiSecret: my-secret
        databases:
          default:
            connector: mysql
            host: host.docker.internal
            database: 'myDB'
            user: root
            password: root
            rawAccess: true
            port: '3306'
            migrations: false
</code></pre>
<p>ok，干掉重来</p>
<pre><code>docker-compose kill
docker-compose down
docker-compose up -d
</code></pre>
<p>结果还是不行，查看容器日志继续抛出错误</p>
<pre><code>[INFO] {} - Starting...
[INFO] {} - Start completed.
[INFO] {} - Starting...
[INFO] {} - Start completed.
Exception in thread &quot;main&quot; java.sql.SQLTransientConnectionException: database - Connection is not available, request timed out after 5006ms.
        at com.zaxxer.hikari.pool.HikariPool.createTimeoutException(HikariPool.java:676)
        at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:190)
        at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:155)
        at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:100)
        at slick.jdbc.hikaricp.HikariCPJdbcDataSource.createConnection(HikariCPJdbcDataSource.scala:14)
        at slick.jdbc.JdbcBackend$BaseSession.&lt;init&gt;(JdbcBackend.scala:494)
        at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:46)
        at slick.jdbc.JdbcBackend$DatabaseDef.createSession(JdbcBackend.scala:37)
        at slick.basic.BasicBackend$DatabaseDef.acquireSession(BasicBackend.scala:250)
        at slick.basic.BasicBackend$DatabaseDef.acquireSession$(BasicBackend.scala:249)
        at slick.jdbc.JdbcBackend$DatabaseDef.acquireSession(JdbcBackend.scala:37)
        at slick.basic.BasicBackend$DatabaseDef$$anon$3.run(BasicBackend.scala:275)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=localhost)(port=3306)(type=master) : Connection refused (Connection refused)
        at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:161)
        at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.connException(ExceptionMapper.java:79)
        at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1040)
        at org.mariadb.jdbc.internal.util.Utils.retrieveProxy(Utils.java:490)
        at org.mariadb.jdbc.MariaDbConnection.newConnection(MariaDbConnection.java:144)
        at org.mariadb.jdbc.Driver.connect(Driver.java:90)
        at slick.jdbc.DriverDataSource.getConnection(DriverDataSource.scala:101)
        at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:369)
        at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:198)
        at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:467)
        at com.zaxxer.hikari.pool.HikariPool.access$100(HikariPool.java:71)
        at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:706)
        at com.zaxxer.hikari.pool.HikariPool$PoolEntryCreator.call(HikariPool.java:692)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        ... 3 more
Caused by: java.net.ConnectException: Connection refused (Connection refused)
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:589)
        at java.net.Socket.connect(Socket.java:538)
        at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connect(AbstractConnectProtocol.java:398)
        at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1032)
        ... 14 more
No log level set, defaulting to INFO.
</code></pre>
<p>发现是MySql连接不上，立马把docker-compose.yml里的host值尝试改成localhost、127.0.0.1，NND还是不行。。。</p>
<p>各种折腾后发现这里犯了一个傻，在docker容器里连接到宿主机的MySql数据库，怎么能用localhost、127.0.0.1这种本地回送地址呢？等于连接回容器里鸭（My youth...）</p>
<p>把host改成宿主机内网地址</p>
<pre><code>connector: mysql
host: 192.168.199.151
database: 'myDB'
user: root
password: root
rawAccess: true
port: '3306'
migrations: false
</code></pre>
<p>干掉重来还是跑不起来，继续查看容器日志，发现连接上了，报的数据库错误</p>
<pre><code>Unknown storage engine 'InnoDB'
</code></pre>
<p>我这MySql默认MyISAM存储引擎，my.ini配置文件修改成</p>
<pre><code>default-storage-engine=INNODB
</code></pre>
<p>重启MySql起不来了，查看MySql日志报错信息：</p>
<pre><code>2019-11-04 16:11:07 0 [Note] InnoDB: Mutexes and rw_locks use Windows interlocked functions
2019-11-04 16:11:07 0 [Note] InnoDB: Uses event mutexes
2019-11-04 16:11:07 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2019-11-04 16:11:07 0 [Note] InnoDB: Number of pools: 1
2019-11-04 16:11:07 0 [Note] InnoDB: Using SSE2 crc32 instructions
2019-11-04 16:11:07 0 [Note] InnoDB: Initializing buffer pool, total size = 64M, instances = 1, chunk size = 64M
2019-11-04 16:11:07 0 [Note] InnoDB: Completed initialization of buffer pool
2019-11-04 16:11:07 0 [ERROR] InnoDB: The Auto-extending innodb_system data file '.\ibdata1' is of a different size 640 pages than specified in the .cnf file: initial 768 pages, max 0 (relevant if non-zero) pages!
2019-11-04 16:11:07 0 [ERROR] InnoDB: Plugin initialization aborted with error Generic error
2019-11-04 16:11:07 0 [Note] InnoDB: Starting shutdown...
2019-11-04 16:11:07 0 [ERROR] Plugin 'InnoDB' init function returned error.
2019-11-04 16:11:07 0 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2019-11-04 16:11:07 0 [Note] Plugin 'FEEDBACK' is disabled.
2019-11-04 16:11:07 0 [ERROR] Unknown/unsupported storage engine: INNODB
2019-11-04 16:11:07 0 [ERROR] Aborting
</code></pre>
<p>提示什么鬼ibdata1实际大小和配置文件中指定的大小不一致，google一下找到解决方法</p>
<p>我这里日志的报错信息<code>...different size 640 pages...</code>，算出其实际大小:640*16/1024=10M</p>
<p>在my.ini里新增一项<code>innodb_data_file_path=ibdata1:10M:autoextend</code></p>
<p>重启MySql终于起来了，docker也跑起来，浏览器输入 <a href="http://localhost:4466/">http://localhost:4466/</a></p>
<p><img src="http://lichengwu.net/content/images/2019/11/image.png" alt="prisma启动成功"></p>
<p>enjoy life</p>
<p>参考：<br>
<a href="https://github.com/prisma/prisma/issues/4434">https://github.com/prisma/prisma/issues/4434</a><br>
<a href="https://www.jianshu.com/p/6ef34ffd5e0c">https://www.jianshu.com/p/6ef34ffd5e0c</a><br>
<a href="https://www.cnblogs.com/ivictor/p/5340822.html">https://www.cnblogs.com/ivictor/p/5340822.html</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[docker TLS证书过期解决办法]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>今天在很久以前安装过docker的win7机器上调试项目，执行<code>docker-compose up -d</code>报错</p>
<pre><code class="language-console">ERROR: SSL error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)
</code></pre>
<p>google了一轮，花了点时间尝试了各种提及到的方法无果。</p>
<p>几经展转发现Docker Machine证书目录</p>
<pre><code>C:\Users\{yourUserName}\.docker\machine\certs
</code></pre>
<p>查看其证书发现已过期一年多。。。</p>
<p><strong>重新生成TLS证书并使用新的证书更新计算机：</strong></p>
<pre><code class="language-console">$ docker-machine regenerate-certs default
Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y
Regenerating TLS certificates
Waiting for</code></pre>]]></description><link>https://lichengwu.net/docker-machine-certificates-have-expired/</link><guid isPermaLink="false">5dbf92718dfa540001cbf005</guid><category><![CDATA[docker]]></category><category><![CDATA[win7]]></category><category><![CDATA[windows]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Mon, 04 Nov 2019 03:33:44 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>今天在很久以前安装过docker的win7机器上调试项目，执行<code>docker-compose up -d</code>报错</p>
<pre><code class="language-console">ERROR: SSL error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:777)
</code></pre>
<p>google了一轮，花了点时间尝试了各种提及到的方法无果。</p>
<p>几经展转发现Docker Machine证书目录</p>
<pre><code>C:\Users\{yourUserName}\.docker\machine\certs
</code></pre>
<p>查看其证书发现已过期一年多。。。</p>
<p><strong>重新生成TLS证书并使用新的证书更新计算机：</strong></p>
<pre><code class="language-console">$ docker-machine regenerate-certs default
Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y
Regenerating TLS certificates
Waiting for SSH to be available...
Detecting the provisioner...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
</code></pre>
<p><strong>重新生成客户端证书：</strong></p>
<pre><code class="language-console">$ docker-machine regenerate-certs --client-certs default
Regenerate TLS machine certs?  Warning: this is irreversible. (y/n): y
Regenerating TLS certificates
Regenerating local certificates
CA certificate is outdated and needs to be regenerated
Creating CA: C:\Users\{yourUserName}\.docker\machine\certs\ca.pem
Client certificate is outdated and needs to be regenerated
Creating client certificate: C:\Users\{yourUserName}\.docker\machine\certs\cert.pem
Waiting for SSH to be available...
Detecting the provisioner...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
</code></pre>
<p>Done</p>
<blockquote>
<p>估计重新生成一下客户端证书就over了。。。</p>
</blockquote>
<p>参考：<a href="https://docs.docker.com/machine/reference/regenerate-certs/">docker-machine regenerate-certs</a></p>
<!--kg-card-end: markdown--><p></p>]]></content:encoded></item><item><title><![CDATA[VeeValidate 3.x 极速入门]]></title><description><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>最近开发前台项目有表单校验需求，因之前做的项目大多都是后台管理系统，用的都是ant-design组件库里的表单校验功能，懵懂的我google一下看还有什么Vue校验轮子，一番对比选择了VeeValidate。在能搜到的中文教程里基本都是基于VeeValidate 2.x写的，但VeeValidate官方版本已经更新到了3.x，作为一个有目标、有理想、有抱负、有要求的大前端当然得紧跟大版本啊。。。</p>
</blockquote>
<h2 id>安装</h2>
<h3 id="yarn">yarn</h3>
<pre><code class="language-bash">yarn add vee-validate
</code></pre>
<h3 id="npm">npm</h3>
<pre><code class="language-bash">npm install vee-validate --save
</code></pre>
<h2 id>使用</h2>
<p>局部导入需要用到的组件及校验规则（需要全局注册组件请参考<a href="https://github.com/logaretm/vee-validate">官方README</a>）：</p>
<pre><code class="language-js">import { extend, ValidationProvider, ValidationObserver } from 'vee-validate'
import { required, email } from 'vee-validate/dist/rules'

// 新增一个required校验规则
extend('required', {
  ...required,      // 官方自带的校验规则
  message: '必填项!!!' // 自定义错误消息</code></pre>]]></description><link>https://lichengwu.net/vee-validate-getting-started/</link><guid isPermaLink="false">5d7ef406b9b9c300011f8002</guid><category><![CDATA[vue]]></category><category><![CDATA[vee-validate]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Tue, 24 Sep 2019 12:30:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><blockquote>
<p>最近开发前台项目有表单校验需求，因之前做的项目大多都是后台管理系统，用的都是ant-design组件库里的表单校验功能，懵懂的我google一下看还有什么Vue校验轮子，一番对比选择了VeeValidate。在能搜到的中文教程里基本都是基于VeeValidate 2.x写的，但VeeValidate官方版本已经更新到了3.x，作为一个有目标、有理想、有抱负、有要求的大前端当然得紧跟大版本啊。。。</p>
</blockquote>
<h2 id>安装</h2>
<h3 id="yarn">yarn</h3>
<pre><code class="language-bash">yarn add vee-validate
</code></pre>
<h3 id="npm">npm</h3>
<pre><code class="language-bash">npm install vee-validate --save
</code></pre>
<h2 id>使用</h2>
<p>局部导入需要用到的组件及校验规则（需要全局注册组件请参考<a href="https://github.com/logaretm/vee-validate">官方README</a>）：</p>
<pre><code class="language-js">import { extend, ValidationProvider, ValidationObserver } from 'vee-validate'
import { required, email } from 'vee-validate/dist/rules'

// 新增一个required校验规则
extend('required', {
  ...required,      // 官方自带的校验规则
  message: '必填项!!!' // 自定义错误消息 
})

// 你也可以直接沿用官方默认规则，但要设置本地化才会提示中文消息
// https://logaretm.github.io/vee-validate/guide/localization.html#i18n
// extend('required', required)

// 新增一个email校验规则，使用官方默认错误消息
extend('email', email)

export default {
  components: {
    ValidationProvider,
    ValidationObserver,
  }
}
</code></pre>
<p><a href="https://logaretm.github.io/vee-validate/api/rules.html">官方内置常用校验规则</a></p>
<h3 id="validationprovider">ValidationProvider组件</h3>
<p>假设我们要校验一个绑定Email的input：</p>
<pre><code class="language-html">&lt;input v-model=&quot;email&quot; type=&quot;text&quot;&gt;
</code></pre>
<p>直接用ValidationProvider组件包裹input，多个校验规则在rules属性里用&quot;|&quot;分隔，错误消息通过v-slot属性传递errors数组：</p>
<pre><code class="language-html">&lt;ValidationProvider rules=&quot;required|email&quot; v-slot=&quot;{ errors }&quot;&gt;
  &lt;input v-model=&quot;email&quot; type=&quot;text&quot;&gt;
  &lt;span&gt;{{ errors[0] }}&lt;/span&gt;
&lt;/ValidationProvider&gt;
</code></pre>
<p>输出：</p>
<pre><code class="language-html">&lt;span&gt;
  &lt;input type=&quot;text&quot;&gt;
  &lt;span&gt;这里是出错消息哦&lt;/span&gt;
&lt;/span&gt;
</code></pre>
<p>ValidationProvider默认会使用span包裹内容，如果想用其它html标签请使用tag属性：</p>
<pre><code class="language-html">&lt;ValidationProvider rules=&quot;required|email&quot; v-slot=&quot;{ errors }&quot; tag=&quot;div&quot;&gt;
  &lt;input v-model=&quot;email&quot; type=&quot;text&quot;&gt;
  &lt;span&gt;{{ errors[0] }}&lt;/span&gt;
&lt;/ValidationProvider&gt;
</code></pre>
<p>输出：</p>
<pre><code class="language-html">&lt;div&gt;
  &lt;input type=&quot;text&quot;&gt;
  &lt;span&gt;这里是出错消息哦&lt;/span&gt;
&lt;/div&gt;
</code></pre>
<p>虽然在使用ValidationProvider组件时通常需要使用v-model，但有时候并不是必需(例如上传文件)，这种情况你可以使用手动校验方法来避免使用v-model。</p>
<pre><code class="language-html">&lt;ValidationProvider
  rules=&quot;required|ext:jpg,png,gif|size:5120&quot;
  v-slot=&quot;{ validate, errors }&quot;
  tag=&quot;div&quot;
&gt;
  &lt;input type=&quot;file&quot; @change=&quot;handleFileChange($event) &amp;&amp; validate($event)&quot;&gt;
  &lt;span v-if=&quot;errors[0]&quot;&gt;{{errors[0]}}&lt;/span&gt;
&lt;/ValidationProvider&gt;
</code></pre>
<p>更多玩法：<a href="https://logaretm.github.io/vee-validate/guide/validation-provider.html">https://logaretm.github.io/vee-validate/guide/validation-provider.html</a></p>
<h3 id="validationobserver">ValidationObserver组件</h3>
<p>如何判断整个表单的当前状态？</p>
<pre><code class="language-html">&lt;template&gt;
  &lt;div&gt;
    &lt;ValidationObserver tag=&quot;form&quot; ref=&quot;obs&quot;&gt;
    
      &lt;ValidationProvider rules=&quot;required&quot; v-slot=&quot;{ errors }&quot;&gt;
        &lt;input type=&quot;text&quot; v-model=&quot;field1&quot; /&gt;
        &lt;span&gt;{{ errors[0] }}&lt;/span&gt;
      &lt;/ValidationProvider&gt;

      &lt;ValidationProvider rules=&quot;required&quot; v-slot=&quot;{ errors }&quot;&gt;
        &lt;input type=&quot;text&quot; v-model=&quot;field2&quot; /&gt;
        &lt;span&gt;{{ errors[0] }}&lt;/span&gt;
      &lt;/ValidationProvider&gt;      
      
      &lt;button @click=&quot;submit&quot;&gt;提交&lt;/button&gt;
      
    &lt;/ValidationObserver&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script&gt;
export default {
  methods: {
    async submit () {
      const isValid = await this.$refs.obs.validate()
      if (!isValid) {
        // 如果没有通过校验执行...
      }

      // 通过校验后执行...
    }
  }
};
&lt;/script&gt;
</code></pre>
<p>更多玩法：<a href="https://logaretm.github.io/vee-validate/guide/validation-observer.html">https://logaretm.github.io/vee-validate/guide/validation-observer.html</a></p>
<h3 id>交互模式</h3>
<p>提拱四种交互模式</p>
<ul>
<li>Aggressive（默认）：当用户按键时触发(on input)</li>
<li>Passive：当表单提交时触发</li>
<li>Lazy：当用户离开输入时触发(on blur or change)</li>
<li>Eager：Aggressive 和 Lazy 的组合，当用户离开输入时，它首先进行校验(on blur or change)，如果输入无效，它将以Aggressive模式进行校验，直到输入再次有效，它将回到Lazy模式</li>
</ul>
<pre><code class="language-html">&lt;ValidationProvider
  mode=&quot;lazy&quot;
  rules=&quot;required&quot;
  v-slot=&quot;{ errors }&quot;
&gt;
  &lt;!-- Some input --&gt;
&lt;/ValidationProvider&gt;
</code></pre>
<p>更多玩法：<a href="https://logaretm.github.io/vee-validate/guide/interaction-and-ux.html">https://logaretm.github.io/vee-validate/guide/interaction-and-ux.html</a></p>
<h3 id>占位符</h3>
<p>例如我想每一个required校验规则错误提示消息都不一样,可以定义规则时message定义使用{<em>field</em>}占位符,ValidationProvider添加name属性定义错误提示消息：</p>
<pre><code class="language-html">&lt;ValidationProvider name=&quot;请输入联系方式&quot; rules=&quot;required&quot; v-slot=&quot;{ errors }&quot;&gt;
   &lt;input type=&quot;text&quot; v-model=&quot;phone&quot; &gt;
   &lt;span v-if=&quot;errors[0]&quot;&gt;{{ errors[0] }}&lt;/span&gt;
&lt;/ValidationProvider&gt;
                  
                  
extend('required', {
  ...required,
  message: '{_field_}'
})
</code></pre>
<p>更多玩法：<a href="https://logaretm.github.io/vee-validate/guide/displaying-errors.html#string-interpolation">https://logaretm.github.io/vee-validate/guide/displaying-errors.html#string-interpolation</a></p>
<h3 id>最后</h3>
<p>到这里相信你已经大概了解这货的基本操作，最后送上一个Demo，让你不再懵懂：</p>
<p><a href="https://codesandbox.io/s/veevalidate-template-r0zir?fontsize=14"><img src="https://codesandbox.io/static/img/play-codesandbox.svg" alt="Edit VeeValidate"></a></p>
<p>enjoy life</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[win7 usb多网卡多个本地连接优先级配置]]></title><description><![CDATA[<p>最近发现spacedesk利用android手机接usb共享网络做扩展屏画面非常流畅，但发现一个问题，只要接入手机usb win7 默认就走usb的无线网络上网，有线网络直接废掉，假如手机不连接wifi直接就上不了网。</p><p>google一下发现在<em>网络连接 </em>里面的<em>高级设置 </em>菜单可以设置网卡的优先顺序</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image.png" class="kg-image"><figcaption>控制面片 &gt; 网络和Internet &gt; 网络连接</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-1.png" class="kg-image"><figcaption>控制面片 &gt; 网络和Internet &gt; 网络连接 &gt; 高级 &gt; 高级设置</figcaption></figure><p>设置好后测试发现仍旧是走手机的网络，无奈之下再google发现很多人也有同样差不多的问题，相关给出的解决方案个人觉得稍微有点复杂，还得认识一下cmd命令敲几下键盘。。。</p><p>后来了解发现路由表的<strong>跃点数</strong>表示路由的优先级，其值越小，优先级越高。于是自己琢磨了一下有了以下解决方案：</p><p>首先输入下面CMD命令查询当前IPv4的路由表信息</p><!--kg-card-begin: markdown--><pre><code class="language-bash">&gt; route print -4
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-2.png" class="kg-image"><figcaption>route print -4</figcaption></figure><p>注意我圈着的部分，当然我这里已经调整过来了，有线网络172.16.x.x的路由跃点数由原来的266改成了110，</p>]]></description><link>https://lichengwu.net/win7-usb-duo-wang-ka-ben-di-lian-jie-you-xian-ji/</link><guid isPermaLink="false">5d666c61e4688e00011f13dc</guid><category><![CDATA[win7]]></category><category><![CDATA[usb共享网络]]></category><category><![CDATA[多网卡]]></category><category><![CDATA[多个本地连接]]></category><category><![CDATA[路由表]]></category><category><![CDATA[跃点数]]></category><dc:creator><![CDATA[Neil]]></dc:creator><pubDate>Thu, 29 Aug 2019 03:55:07 GMT</pubDate><content:encoded><![CDATA[<p>最近发现spacedesk利用android手机接usb共享网络做扩展屏画面非常流畅，但发现一个问题，只要接入手机usb win7 默认就走usb的无线网络上网，有线网络直接废掉，假如手机不连接wifi直接就上不了网。</p><p>google一下发现在<em>网络连接 </em>里面的<em>高级设置 </em>菜单可以设置网卡的优先顺序</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image.png" class="kg-image"><figcaption>控制面片 &gt; 网络和Internet &gt; 网络连接</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-1.png" class="kg-image"><figcaption>控制面片 &gt; 网络和Internet &gt; 网络连接 &gt; 高级 &gt; 高级设置</figcaption></figure><p>设置好后测试发现仍旧是走手机的网络，无奈之下再google发现很多人也有同样差不多的问题，相关给出的解决方案个人觉得稍微有点复杂，还得认识一下cmd命令敲几下键盘。。。</p><p>后来了解发现路由表的<strong>跃点数</strong>表示路由的优先级，其值越小，优先级越高。于是自己琢磨了一下有了以下解决方案：</p><p>首先输入下面CMD命令查询当前IPv4的路由表信息</p><!--kg-card-begin: markdown--><pre><code class="language-bash">&gt; route print -4
</code></pre>
<!--kg-card-end: markdown--><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-2.png" class="kg-image"><figcaption>route print -4</figcaption></figure><p>注意我圈着的部分，当然我这里已经调整过来了，有线网络172.16.x.x的路由跃点数由原来的266改成了110，手机usb网络192.168.x.x的路由跃点数由原来的10改成了400</p><blockquote>这里的跃点数并不就是你所设置的值，而是系统根据设置值生成</blockquote><p>打开网络和共享中心，在<strong>查看活动网络</strong>下点击相关<strong>本地连接</strong>，设置其高级TCP/IP里的跃点</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-3.png" class="kg-image"><figcaption>TCP/IPv4设置</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-4.png" class="kg-image"><figcaption>有线网络</figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-5.png" class="kg-image"><figcaption>手机usb网络</figcaption></figure><blockquote>这里需要注意，像我有线网络原有<strong>默认网关</strong>，就在<strong>默认网关</strong>里面设置跃点</blockquote><p>设置好后再次键入命令查询路由表发现活跃点已经修改成功，但测试上网还是在走手机usb网络。。。</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://lichengwu.net/content/images/2019/08/image-6.png" class="kg-image"><figcaption>Ctrl + Shift + Esc</figcaption></figure><p>莫慌。。。把有线和手机usb都拔掉。。。接入有线。。。接入手机usb。。。</p><p>enjoy life</p><p>参考：</p><p><a href="http://www.koffuxu.com/solution/658.html">双网卡手动配置WIN7路由表</a></p><p><a href="https://blog.51cto.com/5675012/1271523">本地双网卡优先级配置</a></p>]]></content:encoded></item></channel></rss>