<?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[可连续编程100小时不休息，讨论技术方案5小时不喝水。]]></description><link>http://www.hidoge.cn/</link><image><url>http://www.hidoge.cn/favicon.png</url><title>小黄狗前端视觉</title><link>http://www.hidoge.cn/</link></image><generator>Ghost 3.13</generator><lastBuildDate>Tue, 16 Jun 2026 06:17:46 GMT</lastBuildDate><atom:link href="http://www.hidoge.cn/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[An RBAC proposal]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="anrbacproposalinasimpleway">An RBAC proposal in a simple way</h1>
<p>github: <a href="https://github.com/KeroVieux/RBAC-proposal">https://github.com/KeroVieux/RBAC-proposal</a></p>
<blockquote>
<p>Role-based access control (RBAC) is a policy-neutral access-control mechanism defined around roles and privileges.<br>
Further reading: <a href="https://en.wikipedia.org/wiki/Role-based_access_control">https://en.wikipedia.org/wiki/Role-based_access_control</a> &amp;&amp; <a href="https://zhuanlan.zhihu.com/p/63769951">https://zhuanlan.zhihu.com/p/63769951</a></p>
</blockquote>
<p>Even large information shows on</p>]]></description><link>http://www.hidoge.cn/an-rbac-proposal/</link><guid isPermaLink="false">65782261b1d6a600012de692</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Tue, 29 Jun 2021 19:17:26 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="anrbacproposalinasimpleway">An RBAC proposal in a simple way</h1>
<p>github: <a href="https://github.com/KeroVieux/RBAC-proposal">https://github.com/KeroVieux/RBAC-proposal</a></p>
<blockquote>
<p>Role-based access control (RBAC) is a policy-neutral access-control mechanism defined around roles and privileges.<br>
Further reading: <a href="https://en.wikipedia.org/wiki/Role-based_access_control">https://en.wikipedia.org/wiki/Role-based_access_control</a> &amp;&amp; <a href="https://zhuanlan.zhihu.com/p/63769951">https://zhuanlan.zhihu.com/p/63769951</a></p>
</blockquote>
<p>Even large information shows on the internet to tell people what the RBAC is. However, it still makes people feel difficult to understand it and use it in practice.<br>
The concept is clear. The RBAC method enables you to control the permission of the data to show to different roles of users. For instance, people in different departments can read different announcements. In this case, how to set the permission for each announcement?<br>
Following the RBAC concept, I developed a demo to show you how to use it in a simple situation, including database setting, initial data and querying the data.</p>
<h2 id="howtorunthisdemo">How to run this demo</h2>
<ol>
<li><code>npm i</code> to install dependencies</li>
<li><code>node generateRoles.mjs</code> to generate roles</li>
<li><code>node generateUsers.mjs</code> to generate users</li>
<li><code>node generateContent.mjs</code> to generate news and permissions</li>
<li><code>node index.mjs</code> to check the result</li>
<li>Go into the index.mjs to see more details</li>
</ol>
<h2 id="inthisdemowhatyoucanget">In this demo what you can get</h2>
<h3 id="databasesetting">Database setting</h3>
<p><img src="http://dogeapp.cn:9070/images/2021/06/30/5ffb7b839b1a97dbe62eeda936f0dd7e.jpg" alt="http://dogeapp.cn:9070/images/2021/06/30/5ffb7b839b1a97dbe62eeda936f0dd7e.jpg"></p>
<h3 id="queryingtherightnews">Querying the right news</h3>
<ol>
<li>Get the user info.</li>
<li>Get the user's read access for news. Here, you need to filter permissions that have the user's roles in its reaRoles filed &amp;&amp; the user is not in the bannedUser list.</li>
<li>Get news which the user has the right to read</li>
<li>In an extra function, it uses the fuse.js to do the search work.</li>
</ol>
<h2 id="limits">Limits</h2>
<p>It is a demo for the RBAC concept, when you understand it, then you can design your own proposal.<br>
It uses the pouchDB to get the data, in your case, you should shift it to your database or RESTful to query the data.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[qiniu-uploader]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="qiniuuploader">qiniu-uploader</h1>
<blockquote>
<p>使用七牛的用户，相比大部分都是国人，这里就使用中文做一下简介吧！<br>
Hey guy, perhaps it's a wrong way for you here, if you are doing the qiniu in vue and there is a little hassle , I am eager to help , email me.<br>
这是一个针对七牛上传文件的input[type=&quot;file&quot;]，并不是一个封装完成的插件，仅供参考代码应用。但，加入了多选文件、loading效果、基础样式、用户体验的判断，只要照搬代码到你的项目中，基本能满足在客户端的上传动作。</p>
</blockquote>
<p>github:</p>]]></description><link>http://www.hidoge.cn/qiniu-uploader/</link><guid isPermaLink="false">65782261b1d6a600012de691</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Thu, 17 Jun 2021 08:06:21 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="qiniuuploader">qiniu-uploader</h1>
<blockquote>
<p>使用七牛的用户，相比大部分都是国人，这里就使用中文做一下简介吧！<br>
Hey guy, perhaps it's a wrong way for you here, if you are doing the qiniu in vue and there is a little hassle , I am eager to help , email me.<br>
这是一个针对七牛上传文件的input[type=&quot;file&quot;]，并不是一个封装完成的插件，仅供参考代码应用。但，加入了多选文件、loading效果、基础样式、用户体验的判断，只要照搬代码到你的项目中，基本能满足在客户端的上传动作。</p>
</blockquote>
<p>github: <a href="https://github.com/KeroVieux/qiniu-uploader">https://github.com/KeroVieux/qiniu-uploader</a></p>
<h2 id>依赖</h2>
<ul>
<li>axios - 上传和获取token需要</li>
<li>font-awesome - 图标</li>
</ul>
<h2 id>组件说明</h2>
<h3 id="props">props接收参数</h3>
<ul>
<li>accepts - 限制上传文件类型，默认为图片</li>
<li>multiple - 支持多选开关，true/false</li>
<li>maxSize - 最大文件支持，默认为不限制（不建议）</li>
</ul>
<h3 id>方法说明</h3>
<ul>
<li>upload - 选择文件后触发，从api获取token后上传文件到七牛服务器</li>
</ul>
<h2 id>使用例子说明</h2>
<ul>
<li>支持多选、选择完成后自动触发上传动作以及查看</li>
<li>并没有真正的删除已上传的文件</li>
</ul>
<p><img src="http://img.hidoge.cn/FuInm-N6_6oH0cTTCweA2NHZU6r6" alt><br>
<img src="http://img.hidoge.cn/FtFEqaFLB0sdhrSMptw5WhVbt-ve" alt></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[云打印平台]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h2 id>解决需求</h2>
<p>github:<a href="https://github.com/KeroVieux/cloud-printer">https://github.com/KeroVieux/cloud-printer</a><br>
用户在客户端上传自己所需要打印的文档，由映美云打印服务api触发自动打印，管理端可查看各种详细信息</p>
<h2 id>技术栈</h2>
<p>nodejs + mongoDB<br>
vue 2.x</p>
<p><img src="http://img.hidoge.cn/Fpr3t-y7aXYhB9zRTxXK3CSGTW3W" alt><br>
<img src="http://img.hidoge.cn/FrNrAZ9EeL13yEfN4dKaq9p9JnWX" alt><br>
<img src="http://img.hidoge.cn/Fvl15P0w9ncA3T8glQiVv0JudG_M" alt></p>
<!--kg-card-end: markdown-->]]></description><link>http://www.hidoge.cn/yun-da-yin-ping-tai/</link><guid isPermaLink="false">65782261b1d6a600012de690</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Thu, 17 Jun 2021 07:58:30 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id>解决需求</h2>
<p>github:<a href="https://github.com/KeroVieux/cloud-printer">https://github.com/KeroVieux/cloud-printer</a><br>
用户在客户端上传自己所需要打印的文档，由映美云打印服务api触发自动打印，管理端可查看各种详细信息</p>
<h2 id>技术栈</h2>
<p>nodejs + mongoDB<br>
vue 2.x</p>
<p><img src="http://img.hidoge.cn/Fpr3t-y7aXYhB9zRTxXK3CSGTW3W" alt><br>
<img src="http://img.hidoge.cn/FrNrAZ9EeL13yEfN4dKaq9p9JnWX" alt><br>
<img src="http://img.hidoge.cn/Fvl15P0w9ncA3T8glQiVv0JudG_M" alt></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Micro Service Proposal]]></title><description><![CDATA[This a showcase of the 'arc.codes', also a startkit of a serverless proposal ]]></description><link>http://www.hidoge.cn/micro-service-proposal/</link><guid isPermaLink="false">65782261b1d6a600012de68d</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Wed, 03 Jun 2020 14:59:55 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Open source <a href="https://github.com/KeroVieux/doge-micro-api">https://github.com/KeroVieux/doge-micro-api</a></p>
<h1 id="dogemicroapi">doge-micro-api</h1>
<p>This a showcase of the 'arc.codes', also a startkit of a serverless proposal<br>
more <a href="https://arc.codes">https://arc.codes</a></p>
<h2 id>概念</h2>
<ol>
<li>aws的serverless全家桶可以降低运维成本、降低开发成本、提升扩展能力。只是在大陆并不好用（没有大陆服务器），开发者举步维艰（只有英文文档），我们需要思考如何设计架构能够达到上述3个效果</li>
<li>其中FaaS（Functions as a Service）概念，居功至伟，是达到上述效果的关键所在</li>
</ol>
<h3 id>如何降低运维成本</h3>
<ol>
<li>将 构建服务器获取代码 -&gt; 安装依赖 -&gt; 编译 -&gt; 打包 -&gt; 上传 -&gt;重启服务，这个流程简化为服务器获取代码 -&gt; 安装依赖。</li>
<li>能够单独部署子功能</li>
<li>从运维工作中就能定位到报错的原因</li>
</ol>
<h3 id>如何降低开发成本</h3>
<ol>
<li>使用FaaS的思路，每个服务对应一个函数，每一个函数使用自己的依赖</li>
<li>将业务函数和功能函数彻底分离，减少代码中的交叉import，更容易定位报错</li>
<li>将依赖分区管理，每个函数的文件夹内单独安装依赖</li>
<li>不再出现开发人员a改了一个函数，开发人员b发现报错，定位错误的时间缩短</li>
</ol>
<h3 id>如何提升扩展能力</h3>
<ol>
<li>依赖分区后，不再出现不敢动公共依赖导致不敢写公共类</li>
<li>不再出现不敢写公共类，每个开发人员各自维护公共类</li>
</ol>
<h2 id>工具对比</h2>
<h3 id="tars">腾讯出品 - Tars</h3>
<ol>
<li><a href="https://github.com/TarsCloud/Tars">https://github.com/TarsCloud/Tars</a></li>
<li>算了，不想说了，觉得反而增加了开发的负担</li>
</ol>
<h3 id="zeitmicro">zeit专用 - micro</h3>
<ol>
<li><a href="https://github.com/vercel/micro">https://github.com/vercel/micro</a></li>
<li>实现了FaaS的思路</li>
<li>开发体验一般……</li>
</ol>
<h3 id="awsarc">aws专用 - arc</h3>
<ol>
<li><a href="https://github.com/architect/architect">https://github.com/architect/architect</a></li>
<li>实现了FaaS的思路</li>
<li>一键安装/升级所有函数所需要的依赖</li>
<li>自动编译修改后的文件</li>
<li>这里就展示这个工具的使用例子</li>
</ol>
<h2 id="useitasastartkit">Use it as a startkit</h2>
<h3 id="install">Install</h3>
<p><code>npm install -g @architect/architect</code></p>
<h3 id="start">Start</h3>
<p>edit <code>/project/path/.arc</code></p>
<pre><code class="language-text">@app
your-app-name

@http
get /
</code></pre>
<p>execute the init command   <code>arc init</code>  , it will generate files like</p>
<pre><code class="language-text">├── src/
├── http
│   └── get-index
│       ├── .arc-config
│       └── index.js
└── .arc
</code></pre>
<p>execute the sandbox bash  , <code>arc sandbox</code><br>
Now your have got an api which <code>http://localhost:3333/</code> (get)</p>
<h3 id="addanfunction">Add an function</h3>
<p>edit <code>/project/path/.arc</code></p>
<pre><code class="language-text">@app
your-app-name

@http
get /
get /add // what your needed
</code></pre>
<p>execute the init command, <code>arc init</code>, it will generate files like</p>
<pre><code class="language-text">├── src/
├── http
│   └── get-index
│       ├── .arc-config
│       └── index.js
│   └── get-add
│       ├── .arc-config
│       └── index.js
└── .arc
</code></pre>
<p>now your have got one more api which <code>http://localhost:3333/add</code> (get)<br>
<strong>No need restart service</strong></p>
<h3 id="installdependenciesforanewfunction">Install dependencies for a new function</h3>
<pre><code class="language-bash">$ cd /function/path/
$ echo {} &gt; package.json &amp;&amp; yarn add @architect/functions aws-sdk
</code></pre>
<h3 id="installnewdependenciesforafunctionwhichisexist">Install new dependencies for a function which is exist</h3>
<pre><code class="language-bash">$ cd /function/path/
$ yarn add axios
</code></pre>
<h3 id="installupdatedependenciesforafunctionwhichisexistfromthepackagejson">Install/update dependencies for a function which is exist from the package.json</h3>
<pre><code class="language-bash">$ arc hydrate
</code></pre>
<p>or</p>
<pre><code class="language-bash">$ arc hydrate update
</code></pre>
<h3 id="addsomefunctionscanbeusedforotherfunction">Add some functions can be used for other function</h3>
<pre><code class="language-bash">$ cd /project/path/
$ mkidr shared
$ touch dataServerSDK.js
$ cd /project/path/shared
$ echo {} &gt; package.json &amp;&amp; yarn add @architect/functions aws-sdk
</code></pre>
<p>edit the file</p>
<pre><code class="language-javascript">module.exports = function layout(body) {
  return `
  &lt;html&gt;
    &lt;body&gt;
      &lt;h1&gt;layout&lt;/h1&gt;
      ${body}
    &lt;/body&gt;
  &lt;/html&gt;
  `
}
</code></pre>
<p>And then use it</p>
<pre><code class="language-javascript">let layout = require('@architect/shared/layout')

exports.handler = async function http(req) {
  return {
    body: layout('hello world')
  }
}
</code></pre>
<h3 id="deploy">deploy</h3>
<ol>
<li>git push in your side</li>
<li>login your server and execute <code>git pull</code> in the path of project</li>
<li>execute <code>arc hydrate</code> to refresh dependencies</li>
<li>if something goes wrong, just restart the service</li>
</ol>
<h2 id>其他</h2>
<ol>
<li><strong>token授权在哪？</strong> 可以写一个jwt的函数；也可以使用各大平台的oath2，在函数里面与授权服务通信来确定授权和身份；</li>
<li><strong>数据库在哪设置？</strong> 可以写各种insert query的函数，在函数内单独设置与服务器的连接；也可以将数据服务独立，提供rest api，让函数与数据服务使用http通信；</li>
</ol>
<h2 id>开发建议</h2>
<ol>
<li>建议必须的基础服务： 1. 授权服务； 2. 图片服务； 3. 用户资料服务； 4. 数据储存服务；等等，</li>
<li>每个函数需要做好错误处理，拒绝500错误，返回正确的错误信息</li>
<li>所有业务需求在前端处理</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[local-image-server]]></title><description><![CDATA[1. a simple image hosting service used nodejs 
2. running without mysql or mongodb, lowdb is required again (I'm a big fan of lodash)
3. base64 or image from web URL is supported, besides the form submit
4. resize the image to your expect and return base64
5. all images stay in your disk]]></description><link>http://www.hidoge.cn/local-image-server/</link><guid isPermaLink="false">65782261b1d6a600012de68c</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Sun, 31 May 2020 13:32:59 GMT</pubDate><media:content url="http://www.hidoge.cn/content/images/2020/05/Jietu20200531-213359.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><img src="http://www.hidoge.cn/content/images/2020/05/Jietu20200531-213359.jpg" alt="local-image-server"><p>open source: <a href="https://github.com/KeroVieux/local-image-server">https://github.com/KeroVieux/local-image-server</a></p>
<p><a href="http://hidoge.cn:9072/doc/">中文文档</a></p>
<h1 id="localimageserver">local-image-server</h1>
<ol>
<li>a simple image hosting service used nodejs</li>
<li>running without mysql or mongodb, lowdb is required again (I'm a big fan of lodash)</li>
<li>base64 or image from web URL is supported, besides the form submit</li>
<li>resize the image to your expected and return base64</li>
<li>all images stay in your disk</li>
</ol>
<h2 id="gettingstarted">Getting started</h2>
<ol>
<li>
<p>install<br>
<code>yarn</code></p>
</li>
<li>
<p>start<br>
<code>yarn start</code></p>
</li>
<li>
<p>finally<br>
two server have started, one is image server, the other one is data server.(default port is 9071 and 9072)</p>
</li>
</ol>
<h2 id="demo">demo</h2>
<p><a href="http://hidoge.cn:9072/">image list demo</a></p>
<h2 id="deploy">deploy</h2>
<pre><code class="language-bash">$ mkdir uploads
$ pm2 start yarn --interpreter bash --name local-image-server -- start
</code></pre>
<h2 id="whathereprovided">what here provided</h2>
<h3 id="uploadsingleimagefromform">upload single image from form</h3>
<ol>
<li>the name of file input must be 'image'</li>
</ol>
<pre><code>curl -X POST \
  -H &quot;Content-Type: image/png&quot; \
  --data-binary '@test.png'  \
  http://localhost:9071/upload-single
</code></pre>
<p>return</p>
<pre><code class="language-json">{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;: &quot;yNJ7Qa0rH.jpg&quot;}
</code></pre>
<p>your div should be look like this</p>
<pre><code>&lt;form action=&quot;http://localhost:9071/upload-single&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;h2&gt;single&lt;/h2&gt;
  &lt;input type=&quot;file&quot; name=&quot;image&quot;&gt;
  &lt;input type=&quot;submit&quot; value=&quot;submit&quot;&gt;
&lt;/form&gt;
</code></pre>
<h3 id="uploadmultipleimagesfromform">upload multiple images from form</h3>
<ol>
<li>the name of file input must be 'images'</li>
</ol>
<pre><code>curl -X POST \
  -H &quot;Content-Type: image/png&quot; \
  --data-binary '@test.png'  \
  http://localhost:9071/upload-multi
</code></pre>
<p>return</p>
<pre><code class="language-json">[{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;: &quot;yNJ7Qa0rH.jpg&quot;}]
</code></pre>
<p>your div should be look like this</p>
<pre><code>&lt;form action=&quot;http://localhost:9071/upload-multi&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;h2&gt;multi&lt;/h2&gt;
  &lt;input type=&quot;file&quot; name=&quot;images&quot; multiple&gt;
  &lt;input type=&quot;submit&quot; value=&quot;submit&quot;&gt;
&lt;/form&gt;
</code></pre>
<h3 id="base64array">base64 array</h3>
<pre><code>curl -X POST \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;images&quot;: [&quot;base64 str&quot;,&quot;base64 str&quot;]}' \
  http://localhost:9071/upload-base64
</code></pre>
<p>return</p>
<pre><code class="language-json">[{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;: &quot;yNJ7Qa0rH.jpg&quot;}]
</code></pre>
<h3 id="imageurlarray">image url array</h3>
<pre><code>curl -X POST \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;images&quot;: [&quot;web url&quot;,&quot;web url&quot;]}' \
  http://localhost:9071/upload-url
</code></pre>
<p>return</p>
<pre><code class="language-json">[{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;: &quot;yNJ7Qa0rH.jpg&quot;}]
</code></pre>
<h3 id="getimagesobjects">get images objects</h3>
<pre><code>curl -X GET \
  -H &quot;nothing: {{nothing}}&quot; \
  http://localhost:9072/images?id=:id&amp;id=:id
</code></pre>
<p>return</p>
<pre><code class="language-json">[{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;: &quot;yNJ7Qa0rH.jpg&quot;}]
</code></pre>
<h3 id="getthumbs">get thumbs</h3>
<pre><code>curl -X POST \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;filter&quot;: &quot;id=:id&amp;id=:id&quot;' \
  http://localhost:9071/thumbs
</code></pre>
<p>return</p>
<pre><code class="language-json">[{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;:&quot;yNJ7Qa0rH.jpg&quot;,&quot;base64&quot;: &quot;base64&quot;}]
</code></pre>
<h3 id="getimagebyid">get image by id</h3>
<pre><code>curl -X GET \
  -H &quot;nothing: {{nothing}}&quot; \
  http://localhost:9072/images/:id
</code></pre>
<p>return</p>
<pre><code class="language-json">{&quot;id&quot;:&quot;yNJ7Qa0rH&quot;,&quot;fileName&quot;: &quot;yNJ7Qa0rH.jpg&quot;}
</code></pre>
<h3 id="getbase64">get base64</h3>
<pre><code>curl -X GET \
  -H &quot;Content-Type: application/json&quot; \
  http://localhost:9072/image/:id?base64=true
</code></pre>
<p>return base64 string</p>
<h3 id="getfile">get file</h3>
<pre><code>curl -X GET \
  -H &quot;Content-Type: application/json&quot; \
  http://localhost:9072/image/:id
</code></pre>
<p>return file</p>
<h3 id="getspecificsizebase64">get specific size base64</h3>
<pre><code>curl -X GET \
  -H &quot;Content-Type: application/json&quot; \
  http://localhost:9072/sharp/:id?w=100&amp;h=100&amp;format=png
</code></pre>
<p>return base64 string</p>
<h2 id="whynotchevereto">why not chevereto</h2>
<ol>
<li>the only api for upload used get method, so you cannot upload some image within large size</li>
<li>cannot get image with the specific size and format</li>
<li>bad pagination</li>
</ol>
<h2 id="todo">todo</h2>
<ol>
<li>search images in a disk and generate the specific info in the database</li>
<li>build an app for users like chevereto, it should have albums /pagination / tags / full-text search /multiple users</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Fingerprint Web Proposal]]></title><description><![CDATA[There are many guys require to settle cross-domain token, but all most all reply is it not gonna happen, please change your mind.  
Trust me, it easy to make it happen, just follow my step, this proposal will show you something brand new. ]]></description><link>http://www.hidoge.cn/fingerprint-web-proposal/</link><guid isPermaLink="false">65782261b1d6a600012de68b</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Sat, 30 May 2020 22:06:39 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>open source - <a href="https://github.com/KeroVieux/fingerprint-web-auth-proposal">https://github.com/KeroVieux/fingerprint-web-auth-proposal</a></p>
<h2 id="whyishowyouthis">why I show you this</h2>
<p>There are many guys require to settle cross-domain token, but all most all reply is it not gonna happen, please change your mind.<br>
Trust me, it easy to make it happen, just follow my step, this proposal will show you something brand new.</p>
<h2 id="confirmthatwhatyouneedtoaddress">confirm that what you need to address</h2>
<ol>
<li>prohibit users to share the link to someone else;</li>
<li>always can get the user token or the userId, whatever the user link to which domain;</li>
</ol>
<h2 id="howtodo">How to do</h2>
<ol>
<li>use fingerprint2 to identify the user's device</li>
<li>in order to increase the probability of detection that device as unique, get the user's IP is required.</li>
<li>set up a database to store the login record</li>
<li>when a user login one of your app, you insert a record to the database, like { authId, IP, fingerprint,jwtToken }</li>
<li>when a user needs to check the auth status, you can search the database, match this user's { authId, IP, fingerprint }</li>
</ol>
<h2 id="disadvantage">disadvantage</h2>
<ol>
<li>a user shared a link to a man who has the same fingerprint info, that will be leaked information ( I assert just a few people have the same fingerprint info)</li>
<li>users can share the link / authId / fingerprint info with other people(I just can say someone can share their account and password with other people, how can you stop it)</li>
</ol>
<h2 id="3api">3 api</h2>
<h3 id="login">login</h3>
<ol>
<li>after the oauth action, you have got the userId</li>
<li>post the data { userId, fingerprint } to the login api, that will return a authId</li>
<li>store the authId in localstorage</li>
</ol>
<h3 id="check">check</h3>
<ol>
<li>post the data { authId, fingerprint } to the check api, that will return a userId and the jwtToken</li>
<li>if it is not a legal user, the api will return false</li>
</ol>
<h3 id="logout">logout</h3>
<ol>
<li>remove the authId in localstorage</li>
<li>post the data { authId } to the logout api, that will return true.</li>
</ol>
<h2 id="enteranappinadifferentdomain">enter an app in a different domain</h2>
<ol>
<li>the href should be xxx.com?authId=:authId</li>
<li>store the authId in localstorage</li>
<li>post the data { authId, fingerprint } to the check api, that will return a userId</li>
</ol>
<h2 id="whatnow">what now</h2>
<ol>
<li>you can see, when a user stays in your app have the userId, it can assert it as a legal user.</li>
<li>post the userId to your access center server to check the user's auth</li>
<li>post the userId to your user center server to get user profile</li>
<li>use the jwtToken to require api what you need.</li>
</ol>
<h1 id>思路详述</h1>
<h2 id="jwt">当前流行方案JWT</h2>
<h3 id>流程</h3>
<ol>
<li>账号密码登录，得到有时限的token</li>
<li>存入localstorage，请求其他接口在headers.auth中加入token</li>
<li>服务端验证token，匹配权限后进入自身逻辑</li>
</ol>
<h3 id>当前需求冲突</h3>
<ol>
<li>现在的趋势是设备校验身份（参考手机的指纹验证进入app，mac的指纹验证进入系统），密码不再是唯一登录方式，</li>
<li>用户更倾向于自己的设备不应该有授权时限，要求用户重复登录</li>
<li>跨域使用token基本上很困难</li>
</ol>
<h2 id="fingerprintwebauthfwa">重新设计fingerprint web auth - FWA</h2>
<h3 id>说明</h3>
<h4 id>目的</h4>
<ol>
<li>用户只能自己浏览网页，阻止分享他人，泄露信息</li>
<li>能够跨域使用授权信息</li>
<li>取消授权时限，只依赖设备加密</li>
</ol>
<h4 id>使用方法</h4>
<ol>
<li>使用fingerprint2，识别唯一设备(不是绝对成功)</li>
<li>为了让同型号同设置的设备不重复，授权信息表加入ip记录，网络环境改变也需要重新登录</li>
<li>身份校验需要authId fingerprint ip完全匹配</li>
</ol>
<h4 id>已知弊端</h4>
<ol>
<li>用户分享自己的网页给一个拥有一样fingerprint的人，就会泄密(同型号、同批次、同设置、同网络下的你们，关系非同一般，泄密似乎不可怕……)</li>
<li>恶意分享authId fingerprint给他人进行泄密(jwt还恶意分享账号密码呢……)</li>
</ol>
<h4 id="jwt">我一定要用jwt!</h4>
<ol>
<li>当然可以，这个不冲突的，用这个设计思路把jwt token存入授权信息表中，跨域也能获得token</li>
</ol>
<h3 id>第一步 登录</h3>
<h4 id>初次登陆或注销后登陆</h4>
<ol>
<li>if !authId, 则需要扫码或点击按钮进行授权认证，得到userId</li>
<li>在授权信息表储存身份信息, required: userId fingerprint,返回authId</li>
<li>localstorage储存authId</li>
</ol>
<h4 id>再次使用</h4>
<ol>
<li>if authId</li>
<li>请求授权信息表，required: authId fingerprint，同时匹配返回userId</li>
</ol>
<h4 id>检验授权失败</h4>
<ol>
<li>缺少authId</li>
<li>authId fingerprint ip，不完全匹配</li>
</ol>
<h4 id>授权信息表设计</h4>
<ol>
<li>userId</li>
<li>fingerprint</li>
<li>ip</li>
<li>createdAt</li>
</ol>
<h3 id>第二步 跳转其他域名获取授权</h3>
<ol>
<li>跳转网址，query需要authId, 例如 xxx.com?authId=:authId</li>
<li>localstorage储存authId</li>
<li>请求授权信息表，required: authId fingerprint，同时匹配返回userId</li>
</ol>
<h3 id>请求其他接口</h3>
<ol>
<li>将authId fingerprint加密后加入header.Authorization字段中</li>
<li>接口解密header请求授权信息表，required: authId fingerprint，同时匹配返回userId</li>
<li>使用userId查询权限中心，当前用户和当前接口匹配后进入自身逻辑</li>
</ol>
<h3 id>注销</h3>
<ol>
<li>清除localstorage的authId</li>
<li>请求授权信息表，required: authId，软删除该记录</li>
<li>重新登录</li>
</ol>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[简易部署工具]]></title><description><![CDATA[<!--kg-card-begin: markdown--><h1 id="deploytool">deploy-tool</h1>
<h2 id="why">why</h2>
<ol>
<li>小项目，不需要jenkins</li>
<li>无需ftp替换文件</li>
</ol>
<h2 id="todo">todo</h2>
<ol>
<li>部署日志</li>
</ol>
<h2 id="setup">setup</h2>
<ol>
<li><code>yarn</code></li>
<li>That's all</li>
</ol>
<h2 id="configure">configure</h2>
<ol>
<li><code>SERVER</code> refers to your server IP</li>
<li><code>SERVER_PATH</code> refers to the path on your VPS</li>
<li><code>project</code> means the folder name of the remote folder on your VPS</li>
</ol>
<h2 id="use">use</h2>
<p><code>node index.js deploy example</code></p>
<!--kg-card-end: markdown-->]]></description><link>http://www.hidoge.cn/easy-deploy/</link><guid isPermaLink="false">65782261b1d6a600012de68a</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Mon, 18 May 2020 08:44:10 GMT</pubDate><media:content url="http://www.hidoge.cn/content/images/2020/05/Jietu20200518-160229-1.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h1 id="deploytool">deploy-tool</h1>
<h2 id="why">why</h2>
<ol>
<li>小项目，不需要jenkins</li>
<li>无需ftp替换文件</li>
</ol>
<h2 id="todo">todo</h2>
<ol>
<li>部署日志</li>
</ol>
<h2 id="setup">setup</h2>
<ol>
<li><code>yarn</code></li>
<li>That's all</li>
</ol>
<h2 id="configure">configure</h2>
<ol>
<li><code>SERVER</code> refers to your server IP</li>
<li><code>SERVER_PATH</code> refers to the path on your VPS</li>
<li><code>project</code> means the folder name of the remote folder on your VPS</li>
</ol>
<h2 id="use">use</h2>
<img src="http://www.hidoge.cn/content/images/2020/05/Jietu20200518-160229-1.jpg" alt="简易部署工具"><p><code>node index.js deploy example</code></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Doge Hacking Keyboard]]></title><description><![CDATA[DHK-全键可编程，PCB与固件全开源，遵循标准而不失定制扩展的绝佳体验]]></description><link>http://www.hidoge.cn/doge-hacking-keyboard/</link><guid isPermaLink="false">65782261b1d6a600012de689</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Mon, 18 May 2020 08:12:44 GMT</pubDate><media:content url="http://www.hidoge.cn/content/images/2020/05/DSC02027.JPG" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="dogehackingkeyboard">专业人士的键盘 - Doge Hacking Keyboard</h2>
<img src="http://www.hidoge.cn/content/images/2020/05/DSC02027.JPG" alt="Doge Hacking Keyboard"><p>DHK-全键可编程，PCB与固件全开源，遵循标准而不失定制扩展的绝佳体验</p>
<ol>
<li>全部材料的选用都是充分考虑易购买、低成本的决定</li>
<li>键位布局充分考虑十指盲打的分工</li>
<li>选用pro micro作为主控，价格甚至低于裸芯片零售价</li>
<li>所有设计都考虑了手工焊接和SMT贴片的可能性</li>
<li>除了用户DIY扩展之外，官方自带标准扩展件，适合初级和骨灰级玩家</li>
<li>全部软件、硬件都开源共享，用户可定制的范围超乎想象</li>
</ol>
<p><img src="http://dogeapp.cn:9070/images/2020/05/05/55591b8c9b3b1456e7f708cb6ebbafe8.jpg" alt="Doge Hacking Keyboard"></p>
<h3 id>提供多种扩展件</h3>
<p><img src="http://dogeapp.cn:9070/images/2020/05/05/1986a8878f49e46a3f4628efd865ee5e.jpg" alt="Doge Hacking Keyboard"><br>
<img src="http://dogeapp.cn:9070/images/2020/05/05/fac36e1b651c49b10fb889d51101f35e.jpg" alt="Doge Hacking Keyboard"></p>
<h4 id="pcb">全部软件、硬件都开源共享，除了可以给我提出定制需求，更可以自行深度定制。如果需要增加按键，我提供三种不同的扩展件；如果需要人体工学设计，我提供替换外壳；如果需要具有相当个性标签的PCB或配套软件，我提供定制服务。</h4>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[OpenWrt的阿里域名ddns工具]]></title><description><![CDATA[简单设置与部署，跟第三方ddns服务商撇清关系！]]></description><link>http://www.hidoge.cn/openwrt-ddns-ali/</link><guid isPermaLink="false">65782261b1d6a600012de688</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Mon, 18 May 2020 08:03:46 GMT</pubDate><media:content url="http://www.hidoge.cn/content/images/2020/05/Jietu20200518-160229.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="whythistool">Why this tool</h2>
<ol>
<li>国内DDNS服务商基本上就花生壳一家独大，我体验期间发现它非常贴心的帮你限速、提醒你付费等等，关键是稳定性还一般</li>
<li>在路由器上就能解决的问题，为何要交给第三方呢？仅仅需要简单的设置</li>
<li>源码：<a href="http://https://github.com/KeroVieux/ali-ddns">https://github.com/KeroVieux/ali-ddns</a></li>
</ol>
<h2 id>实现方法</h2>
<ol>
<li>部署此代码到你的wrt-open路由器上</li>
<li>定时执行（建议5分钟）</li>
<li>判断当前ip与线上所解析的ip不吻合则请求api修改ip</li>
</ol>
<h2 id>文件内必填参数</h2>
<ol>
<li><code>accessKeyId</code></li>
<li><code>accessKeySecret</code></li>
<li><code>RecordId</code></li>
<li>lastCheck路径</li>
<li>当前ip路径</li>
</ol>
<h2 id="setup">set up</h2>
<ol>
<li>fill up the argument which is required</li>
<li><code>yarn</code></li>
<li>done</li>
</ol>
<h2 id="howtorun">how to run</h2>
<img src="http://www.hidoge.cn/content/images/2020/05/Jietu20200518-160229.jpg" alt="OpenWrt的阿里域名ddns工具"><p><code>npm run start</code></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[千兆家用路由器wifi认证方案]]></title><description><![CDATA[为了更低成本的实现专业的公共wifi热点（参考机场wifi）对开源固件做了一番修改与配置]]></description><link>http://www.hidoge.cn/router-web-auth/</link><guid isPermaLink="false">65782261b1d6a600012de687</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Mon, 18 May 2020 07:46:17 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id>当前的两难境地描述：</h2>
<ol>
<li>大众所认识的品牌路由器在售带web认证接入wifi的型号屈指可数，几乎只有百兆企业路由可选择；</li>
<li>杂牌路由不一定敢使用，担心固件有后门，埋下隐患；</li>
<li>主路由使用千兆路由，再由一个带web认证的百兆路由开启guest wifi，通常这类路由的无线功能比较弱鸡，所以还得继续给这个guest路由扩展AP，导致成本直线上升；</li>
<li>下图为其中一个带web认证接入功能的路由，不一一列举，其实都差不多</li>
</ol>
<p><img src="http://dogeapp.cn:9070/images/2020/05/18/2b2336644ecf49baa7d9c291ef136f2e.png" alt="2b2336644ecf49baa7d9c291ef136f2e.png"><br>
<img src="http://dogeapp.cn:9070/images/2020/05/18/e8c74a7a07867ed7fbec21d9a621e5e4.png" alt="e8c74a7a07867ed7fbec21d9a621e5e4.png"></p>
<h2 id>解决方案</h2>
<ol>
<li>使用wrt开源固件，定制一个与自用网络绝对隔离的guest网络；</li>
<li>对guest网络配置限时、限速、限定访问、白名单、黑名单等功能；</li>
<li>实现过程过于复杂和坎坷，不在此乱说了。。私聊。。</li>
<li>设计扫码连接指引的广告单张、连接页面、与链接成功页面（此步骤对品牌宣传有相当的作用），如下图</li>
</ol>
<p>广告单张<br>
<img src="http://dogeapp.cn:9070/images/2020/05/18/bdb0184513cab84cd2b4e1b65dc306f1.jpg" alt="bdb0184513cab84cd2b4e1b65dc306f1.jpg"></p>
<p>连接页面<br>
<img src="http://dogeapp.cn:9070/images/2020/05/18/5a02ba36e1ccb1c8b7625b37a327872f.jpg" alt="5a02ba36e1ccb1c8b7625b37a327872f.jpg"></p>
<p>成功页面<br>
<img src="http://dogeapp.cn:9070/images/2020/05/18/eead86e4b1ca2a4c4336ea14339bea76.jpg" alt="eead86e4b1ca2a4c4336ea14339bea76.jpg"></p>
<!--kg-card-end: markdown--><p></p><h2></h2>]]></content:encoded></item><item><title><![CDATA[QMK Firmware Builder]]></title><description><![CDATA[<h1 id="keyboard-firmware-builder">Keyboard Firmware Builder</h1><h2 id="reasons-for-updating-this-project-so-much">Reasons for updating this project so much</h2><ol><li>Origin repo had stopped updating and do not reply to any issues since 21 Jan 2017</li><li>Readme for that is not enough for people to make the project work.</li><li>The master of the project seems not familiar with coding in</li></ol>]]></description><link>http://www.hidoge.cn/qmk-firmware-builder/</link><guid isPermaLink="false">65782261b1d6a600012de680</guid><dc:creator><![CDATA[kero]]></dc:creator><pubDate>Thu, 16 Apr 2020 17:33:14 GMT</pubDate><media:content url="http://www.hidoge.cn/content/images/2020/04/qmk1.jpg" medium="image"/><content:encoded><![CDATA[<h1 id="keyboard-firmware-builder">Keyboard Firmware Builder</h1><h2 id="reasons-for-updating-this-project-so-much">Reasons for updating this project so much</h2><ol><li>Origin repo had stopped updating and do not reply to any issues since 21 Jan 2017</li><li>Readme for that is not enough for people to make the project work.</li><li>The master of the project seems not familiar with coding in front-end</li></ol><h2 id="new-feature">New feature</h2><ol><li>support async await</li><li>add localstorage for separate different user</li><li>add database to store configuration for everybody(couch DB)</li><li>add watch file updating to auto compile to .js</li><li>add bulma.io as a new face</li><li>have not done yet...</li></ol><h2 id="setup">Setup</h2><img src="http://www.hidoge.cn/content/images/2020/04/qmk1.jpg" alt="QMK Firmware Builder"><p>To set up the project for development, run <code>npm install</code> in the root of the project to install dependencies.</p><p>Create a <code>local.json</code> file in <code>src/const</code>, in the format(like me):</p><pre><code>{
	"DB_URL": "database url",
	"DB_NAME": "database name",
	"API": "http://localhost:5004"
}
</code></pre><h2 id="run-your-own-compile-server">run your own compile server</h2><p>First, <code>dfu-programmer</code> and <code>avr-gcc</code> is required.</p><pre><code>$ cd server
$ node index.js
</code></pre><p>And then <code>http://localhost:5004</code> is your builder server(look up to local.json)</p><h2 id="developing">developing</h2><pre><code>$ npm run deploy
</code></pre><p>And then it will auto compile your updating into <code>/static</code> folder, until you stop this server</p><h2 id="preview-your-work">preview your work</h2><pre><code>$npm i -g http-server
$ cd static
$ http-server
</code></pre><p>voilà, <code>http://127.0.0.1</code> is your work</p><h2 id="deploy">deploy</h2><ol><li>upload folders <code>server</code> and <code>static</code> to your vps</li><li>start your builder server(see above)</li><li>http-server or apache or nginx whatever, open a link for <code>static</code></li></ol><h2 id="online-website">Online website</h2><p>[<a href="http://hidoge.cn:8080/qmk-builder/">http://hidoge.cn:8080/qmk-builder/</a>](<a href="http://hidoge.cn:8080/qmk-builder/">http://hidoge.cn:8080/qmk-builder/</a>)</p><h2 id="pics">PICS</h2><figure class="kg-card kg-image-card"><img src="http://www.hidoge.cn/content/images/2020/04/qmk1.jpg" class="kg-image" alt="QMK Firmware Builder"></figure>]]></content:encoded></item></channel></rss>