<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>晴耕雨讀</title>
  <subtitle>程序員，最佳實踐和閱讀愛好者，Vim、Archlinux、Mac、iOS擁躉，帝都低端人口。</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://0x3f.org/"/>
  <updated>2018-12-18T10:05:47.752Z</updated>
  <id>http://0x3f.org/</id>
  
  <author>
    <name>晴耕雨讀</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>用ALE替換了Syntastic</title>
    <link href="http://0x3f.org/post/replace-syntastic-with-ale/"/>
    <id>http://0x3f.org/post/replace-syntastic-with-ale/</id>
    <published>2018-12-12T12:42:10.000Z</published>
    <updated>2018-12-18T10:05:47.752Z</updated>
    
    <content type="html"><![CDATA[<p>習慣頻繁地保存源碼，但是每次保存都有明顯的卡頓，於是用Vim自己的調優功能跟蹤了一下。</p>
<p>依次執行以下命令：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">:profile start profile.log</div><div class="line">:profile file *</div><div class="line">:profile func *</div></pre></td></tr></table></figure>
<p>然後執行保存操作，再執行以下命令：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">:profile pause</div><div class="line">:noautocmd qall!</div></pre></td></tr></table></figure>
<p>在當前目錄下生成的文件profile.log里，看到執行時間最長的是Syntastic的函數，禁用這個擴展後保存果然比原來快多了。</p>
<p>但是Syntastic是個很有用的擴展，所以Google一下有沒有異步執行的方法，偶然發現了ALE，主要特性就是異步執行。試用之後覺得很好用，就把前者卸了。</p>
<p>ALE的初始配置如下：</p>
<figure class="highlight vim"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div></pre></td><td class="code"><pre><div class="line"><span class="comment">" ALE</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_sign_column_always</span> = <span class="number">1</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_set_highlights</span> = <span class="number">0</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:airline</span>#extensions#ale#enabled = <span class="number">1</span></div><div class="line"><span class="comment">"自定義error和warning圖標</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_sign_error</span> = <span class="string">'✗'</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_sign_warning</span> = <span class="string">'⚠'</span></div><div class="line"><span class="comment">" 顯示Linter名稱,出錯或警告等相關信息</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_echo_msg_error_str</span> = <span class="string">'E'</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_echo_msg_warning_str</span> = <span class="string">'W'</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_echo_msg_format</span> = <span class="string">'[%linter%] %s [%severity%]'</span></div><div class="line"><span class="comment">" PHP</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_php_phpcs_standard</span> = <span class="string">'PSR2'</span></div><div class="line"><span class="keyword">let</span> <span class="variable">g:ale_php_phpmd_ruleset</span> = <span class="string">'~/.phpmd.xml'</span></div><div class="line"><span class="comment">" 普通模式下，sp前往上一個錯誤或警告，sn前往下一個錯誤或警告</span></div><div class="line"><span class="keyword">nmap</span> <span class="keyword">sp</span> <span class="symbol">&lt;Plug&gt;</span>(ale_previous_wrap)</div><div class="line"><span class="keyword">nmap</span> <span class="keyword">sn</span> <span class="symbol">&lt;Plug&gt;</span>(ale_next_wrap)</div><div class="line"><span class="comment">" 觸發/關閉語法檢查</span></div><div class="line"><span class="keyword">nmap</span> <span class="symbol">&lt;Leader&gt;</span>at :ALEToggle<span class="symbol">&lt;CR&gt;</span></div><div class="line"><span class="comment">" 查看錯誤或警告的詳細信息</span></div><div class="line"><span class="keyword">nmap</span> <span class="symbol">&lt;Leader&gt;</span>ad :ALEDetail<span class="symbol">&lt;CR&gt;</span></div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;習慣頻繁地保存源碼，但是每次保存都有明顯的卡頓，於是用Vim自己的調優功能跟蹤了一下。&lt;/p&gt;
&lt;p&gt;依次執行以下命令：&lt;/p&gt;
&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;div 
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="vim" scheme="http://0x3f.org/tags/vim/"/>
    
  </entry>
  
  <entry>
    <title>配置鼠須管的特殊符號輸入</title>
    <link href="http://0x3f.org/post/input-punctuations-with-rime/"/>
    <id>http://0x3f.org/post/input-punctuations-with-rime/</id>
    <published>2018-10-13T03:59:50.000Z</published>
    <updated>2018-11-04T04:35:09.983Z</updated>
    
    <content type="html"><![CDATA[<p><em>開源工具最常見的問題就是文檔不全，實現一個需求的時候隻能苦苦Google，甚至連蒙帶猜。這也是我逐漸傾向買用戶體驗更好的收費軟件的原因。</em></p>
<p>鼠須管是自帶特殊符號碼表的，在用戶配置目錄中的<code>symbols.yaml</code>，但是有的碼表需要手動配置。經過查資料和摸索，關鍵在於以下幾項配置：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="attr">punctuator:</span></div><div class="line"><span class="attr">  import_preset:</span> <span class="string">symbols</span></div><div class="line"></div><div class="line"><span class="attr">recognizer:</span></div><div class="line"><span class="attr">  import_preset:</span> <span class="string">default</span></div><div class="line"><span class="attr">  patterns:</span></div><div class="line"><span class="attr">    punct:</span> <span class="string">"^/([a-z]+|[0-9]0?)$"</span></div></pre></td></tr></table></figure>
<p>然後就可以通過<code>【/】+【編碼】</code>的方式顯示符號備選項了，具體的編碼可以到<code>symbols.yaml</code>裏看，當然一般爲了方便定制該碼表，會複制並重命名該文件，然後上述的配置項裏也要做相應的修改。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;em&gt;開源工具最常見的問題就是文檔不全，實現一個需求的時候隻能苦苦Google，甚至連蒙帶猜。這也是我逐漸傾向買用戶體驗更好的收費軟件的原因。&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;鼠須管是自帶特殊符號碼表的，在用戶配置目錄中的&lt;code&gt;symbols.yaml&lt;/code&gt;，但是有
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="Mac" scheme="http://0x3f.org/tags/mac/"/>
    
  </entry>
  
  <entry>
    <title>我叫王戰鬥</title>
    <link href="http://0x3f.org/post/i-am-wang-zhandou/"/>
    <id>http://0x3f.org/post/i-am-wang-zhandou/</id>
    <published>2018-07-01T08:46:32.000Z</published>
    <updated>2018-11-04T04:36:15.686Z</updated>
    
    <content type="html"><![CDATA[<p>我叫王戰鬥，男，喵星人，狸花族，現年四個半月，折合成你們兩腳獸的年齡算7歲了。</p>
<p>雖然剛降臨你星不久，但是我已經能馴服和駕馭兩腳獸這種低等生物了。因為我發現這種生物本性里有一個致命弱點：對它很好反而不會珍惜，故作高冷卻奴顏婢膝求抱抱！我們喵星管這叫「賤」。</p>
<p>開始的時候，我的馭獸術還不熟練，而且我酷愛往兩腳獸的脖子里鑽，然後蹭它們的臉。結果它們不乾了，在我才兩個月零九天的時候就把我交給了現在這頭兩腳獸。是它們不懂喵星習俗好不好？！而且作為一個剛斷奶的小正太，賣個萌怎麼啦，怪我咯？</p>
<p>我一直在暗中觀察現在這頭兩腳獸。發現每隔五天，它都會在巢穴里待上兩天，然後在接下來的五天里每天都消失一段時間。雖然有點好奇，不過也不是什麼大事，只要我有吃有喝、兩腳獸按時鏟屎，每天給它放個風什麼的我也OK，這是我們喵星高等生物的自我修養。</p>
<p>不過還是要測試一下這貨的馴服度。所以我命令它伺候我睡個午覺：<br><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fwvx0d5683j31kw1kwb29.jpg" alt=""></p>
<p>這貨竟然沒有反抗！！！</p>
<p>有一天我發現它竟然在偷看我練習家傳絕學「黑虎掏心」，我就瞪它，就瞪它：<br><img src="https://ws1.sinaimg.cn/large/006tNbRwly1fwvx0z5chyj31ei1ei4qp.jpg" alt=""></p>
<p>有時候兩腳獸全神貫注地照鏡子，我就想看看它看的啥，然後它就扒拉我，我想一定是我高大威猛的身軀擋住它了：<br><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fwvx1dzxegj31kw16okjm.jpg" alt=""></p>
<p>這老頭叫馬霸霸，挺能白話的，它的巢穴已經被我軍佔領了：<br><img src="https://ws1.sinaimg.cn/large/006tNbRwly1fwvx1v8jh3j31kw1kwhdu.jpg" alt=""></p>
<p>那天兩腳獸帶回來一隻老鼠，我一眼就看出來是假的，但是這貨一碰就叫啊，然後我就停不下來了，你星管這叫口嫌體正直，看著兩腳獸謎之微笑，我覺得中了奸計：<br><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fwvx2fq5ltj30sz0prq8x.jpg" alt=""></p>
<p>更有甚者，它竟然趁我睡著的時候拍我裸照，還傳到網上：<br><img src="https://ws1.sinaimg.cn/large/006tNbRwly1fwvx2ix4jej31kw23ve84.jpg" alt=""></p>
<p>生亦何歡，死亦何懼。趁兩腳獸上廁所的時候，叼走了捲紙，然後撕稀碎，有能耐學我們喵星人上完廁所自己舔乾淨啊？！<br><img src="https://ws2.sinaimg.cn/large/006tNbRwly1fwvx2zgpawj31kw1kw1kz.jpg" alt=""></p>
<p>沒想到報復來得如此突然，兩腳獸不知道從哪兒搞了一瓶毒氣，走到哪兒揣到哪兒，我一想搞事情就各種噴：<br><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fwvx332k34j30lc0sgn0a.jpg" alt=""></p>
<p>真臭啊，臭到懷疑喵生啊！<br><img src="https://ws1.sinaimg.cn/large/006tNbRwly1fwvx3jj4ktj31kw23v1kz.jpg" alt=""></p>
<p>話說回來，大部分時間兩腳獸還是沒那麼討厭。比如這個會噴水的盒子，被我霸佔後就成了我最常喝水的東西兼洗腳盆：<br><img src="https://ws3.sinaimg.cn/large/006tNbRwly1fwvxatojbkj31260v9k0s.jpg" alt=""></p>
<p>兩腳獸的廚藝也不賴：<br><img src="https://ws3.sinaimg.cn/large/006tNbRwly1fwvxb51icjj31kw1kw1kz.jpg" alt=""></p>
<p>吹噓自己慷慨的時候，兩腳獸就指著這口袋說：「比我吃得都好。」其實就是618的打折貨。<br><img src="https://ws3.sinaimg.cn/large/006tNbRwly1fwvx61t9ogj31kw1kw1kz.jpg" alt=""></p>
<p>兩腳獸就是個肥宅兼Nerd，且不說為了給我做飯專門買了台電動切碎機和保鮮盒。鏟個屎都裝絕命毒師：<br><img src="https://ws2.sinaimg.cn/large/006tNbRwly1fwvx6f8zwzj31kw14fhdv.jpg" alt=""></p>
<p>某天整了把稀奇古怪的東西在床上、沙發上各種吸，完事非要說是我乾的：<br><img src="https://ws2.sinaimg.cn/large/006tNbRwly1fwvx709q7qj31kw16o4qq.jpg" alt=""></p>
<p>我的天啊！不就掉個毛麼，全宇宙只有你們兩腳獸光著屁股滿世界跑！<br><img src="https://ws1.sinaimg.cn/large/006tNbRwly1fwvx75b1f9j31kw1kw7wi.jpg" alt=""></p>
<p>我來，我見，我征服。我是王戰鬥，一個普通的馴兽師。<br><img src="https://ws3.sinaimg.cn/large/006tNbRwly1fwvx7kbr2hj30sg0sg0zr.jpg" alt=""></p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;我叫王戰鬥，男，喵星人，狸花族，現年四個半月，折合成你們兩腳獸的年齡算7歲了。&lt;/p&gt;
&lt;p&gt;雖然剛降臨你星不久，但是我已經能馴服和駕馭兩腳獸這種低等生物了。因為我發現這種生物本性里有一個致命弱點：對它很好反而不會珍惜，故作高冷卻奴顏婢膝求抱抱！我們喵星管這叫「賤」。&lt;/p
    
    </summary>
    
      <category term="晴耕雨讀" scheme="http://0x3f.org/categories/%E6%99%B4%E8%80%95%E9%9B%A8%E8%AE%80/"/>
    
    
      <category term="隨筆" scheme="http://0x3f.org/tags/%E9%9A%A8%E7%AD%86/"/>
    
      <category term="王戰鬥" scheme="http://0x3f.org/tags/%E7%8E%8B%E6%88%B0%E9%AC%A5/"/>
    
  </entry>
  
  <entry>
    <title>生成PDF的方案調研</title>
    <link href="http://0x3f.org/post/pdf-creating-solutions/"/>
    <id>http://0x3f.org/post/pdf-creating-solutions/</id>
    <published>2018-05-16T07:41:36.000Z</published>
    <updated>2018-11-04T04:35:09.947Z</updated>
    
    <content type="html"><![CDATA[<h2 id="結論"><a href="#結論" class="headerlink" title="結論"></a>結論</h2><p>傾向於通過wkhtmltopdf+消息隊列實現。</p>
<p>工作流程：</p>
<ol>
<li>用戶保存表單</li>
<li>推送生成pdf的任務到隊列</li>
<li>同時頁面顯示「正在生成PDF文檔，請稍候」並輪詢後端接口</li>
<li>PDF生成後，頁面顯示下載按鈕</li>
</ol>
<h2 id="後端"><a href="#後端" class="headerlink" title="後端"></a>後端</h2><h3 id="dompdf"><a href="#dompdf" class="headerlink" title="dompdf"></a>dompdf</h3><p>純PHP實現。工作原理是把HTML轉換成PDF。</p>
<p>優點：</p>
<ol>
<li>不需要PHP調用命令行，安全性高。</li>
</ol>
<p>缺點：</p>
<ol>
<li>HTML/CSS支持不完全，實測多個網頁轉換後排版錯亂。</li>
<li>中文網頁轉換後，中文都是問號（網上說有解決辦法<a href="http://www.cnblogs.com/xxoome/p/6083542.html" target="_blank" rel="external">1</a>、<a href="http://blog.51cto.com/lampzxr/1916038" target="_blank" rel="external">2</a>，未測試）。</li>
<li>CPU佔用比較高（網上的說法，沒有實測具體有多高）。</li>
</ol>
<p>參考：</p>
<ul>
<li><a href="https///github.com/barryvdh/laravel-dompdf">laravel-dompdf主頁</a></li>
</ul>
<h3 id="mpdf"><a href="#mpdf" class="headerlink" title="mpdf"></a>mpdf</h3><p>純PHP實現。工作原理是把HTML轉換成PDF。</p>
<p>優點：</p>
<ol>
<li>不需要PHP調用命令行，安全性高。</li>
</ol>
<p>缺點（未實測）：</p>
<ol>
<li>HTML/CSS支持不完整。</li>
<li>生成PDF耗時長。</li>
</ol>
<p>參考：</p>
<ul>
<li><a href="https///github.com/niklasravnsborg/laravel-pdf">laravel-pdf主頁</a></li>
<li><a href="https///mpdf.github.io">mpdf文檔</a></li>
<li><a href="https///github.com/mpdf/mpdf">mpdf主頁</a></li>
<li><a href="http://www.cnblogs.com/attitudeY/p/7297948.html" target="_blank" rel="external">mpdf與fpdf的使用比較</a></li>
</ul>
<h3 id="PDFtk-Server"><a href="#PDFtk-Server" class="headerlink" title="PDFtk Server"></a>PDFtk Server</h3><p>PDFtk Server是個命令行程序。工作原理是利用FDF表單替換PDF模板中的佔位符。實現方案有：純PHP實現FDF + PDFtk、FPDI + PDFtk。</p>
<p>優點：</p>
<ol>
<li>直接替換PDF模板，實現成本低，最大程度保證生成的PDF的效果。</li>
</ol>
<p>缺點：</p>
<ol>
<li>需要允許PHP調用命令行，有安全隱患。</li>
<li>只能實現簡單的字符串替換（例如公司名稱），不能替換有格式文本。</li>
</ol>
<p>參考：</p>
<ul>
<li><a href="https///www.setasign.com/products/fpdi/manual/#p-58">FPDI</a></li>
<li><a href="http://php.net/manual/zh/intro.fdf.php" target="_blank" rel="external">PHP的FDF手冊</a></li>
<li><a href="https///stackoverflow.com/questions/1389964/merge-fdf-data-into-a-pdf-file-using-php">PDFtk的使用方法</a></li>
<li><a href="https///www.sitepoint.com/filling-pdf-forms-pdftk-php/">純PHP實現FDF + PDFtk</a></li>
</ul>
<h3 id="wkhtmltopdf"><a href="#wkhtmltopdf" class="headerlink" title="wkhtmltopdf"></a>wkhtmltopdf</h3><p>wkhtmltopdf是個命令行程序。工作原理是轉換HTML到PDF。實現方案是laravel-snappy。</p>
<p>優點：</p>
<ol>
<li>由於內嵌webkit核心，HTML/CSS的支持沒有問題。</li>
</ol>
<p>缺點：</p>
<ol>
<li>需要允許PHP調用命令行，有安全隱患。</li>
<li>wkhtmltopdf體積40M，併發較多時影響服務器性能和穩定性（需要考慮用隊列輔助實現，異步執行，需要需求變更交互方式）。</li>
</ol>
<p>參考：</p>
<ul>
<li><a href="https///github.com/barryvdh/laravel-snappy">laravel-snappy主頁</a></li>
</ul>
<h3 id="CutyCapt"><a href="#CutyCapt" class="headerlink" title="CutyCapt"></a>CutyCapt</h3><p>命令行程序。工作原理和wkhtmtopdf相同。</p>
<p>優缺點同wkhtmltopdf，但是最近的更新在13年。</p>
<p>參考：</p>
<ul>
<li><a href="http://cutycapt.sourceforge.net" target="_blank" rel="external">CutyCapt主頁</a></li>
</ul>
<h3 id="Prince"><a href="#Prince" class="headerlink" title="Prince"></a>Prince</h3><p>命令行程序。工作原理是轉換HTML到PDF。</p>
<p>優點：</p>
<ol>
<li>HTML/CSS的支持很好。</li>
<li>文檔很全</li>
</ol>
<p>缺點：</p>
<ol>
<li>收費，而且很貴。（免費版會在輸出的文檔右上角打一個Logo）</li>
<li>需要允許PHP執行命令行，有安全隱患。</li>
<li>需要考慮用隊列輔助實現，異步執行，需要需求變更交互方式。</li>
</ol>
<p>參考：</p>
<ul>
<li><a href="https///www.princexml.com">Prince官網</a></li>
</ul>
<h2 id="前端"><a href="#前端" class="headerlink" title="前端"></a>前端</h2><h3 id="jsPDF"><a href="#jsPDF" class="headerlink" title="jsPDF"></a>jsPDF</h3><p>工作原理有兩種：編程方式動態生成和轉換HTML到PDF。有三個插件支持轉換HTML到PDF：fromHTML、addHTML和html2pdf。</p>
<p>fromHTML最老，優點是直接轉換HTML到PDF，缺點是對複雜的HTML/CSS支持得不好。實測結果，UTF-8編碼的中文網頁，轉換到PDF都是亂碼。</p>
<p>addHTML較新，但目前處於deprecated狀態，利用html2canvas/rasterizeHTML創建一個canvas，然後把HTML轉換成圖片、再轉換成PDF。實測結果，對中文網頁和CSS支持得都不錯，但是對分頁支持得不好，指定分頁選項後圖片被拉伸並強行分割，很難看。</p>
<p>html2pdf是正在開發的功能，還沒完成。</p>
<p>參考：</p>
<ul>
<li><a href="https://stackoverflow.com/questions/44778260/what-are-the-differences-between-jspdfs-methods-addhtml-and-fromhtml" target="_blank" rel="external">https://stackoverflow.com/questions/44778260/what-are-the-differences-between-jspdfs-methods-addhtml-and-fromhtml</a></li>
</ul>
<h3 id="pdfkit"><a href="#pdfkit" class="headerlink" title="pdfkit"></a>pdfkit</h3><p>只能通過編程（//調用接口指定內容、分頁等相關屬性//）生成PDF，不支持從HTML轉換到PDF。</p>
<h3 id="pdfmake"><a href="#pdfmake" class="headerlink" title="pdfmake"></a>pdfmake</h3><p>據說擴展自pdfkit。只能通過編程（//調用接口指定內容、分頁等相關屬性//）生成PDF，不支持從HTML轉換到PDF。而且需要引用字體文件轉換成的js文件，不適合中文內容。</p>
<h2 id="變通方案"><a href="#變通方案" class="headerlink" title="變通方案"></a>變通方案</h2><h3 id="利用瀏覽器打印PDF"><a href="#利用瀏覽器打印PDF" class="headerlink" title="利用瀏覽器打印PDF"></a>利用瀏覽器打印PDF</h3><p>Chrome、Firefox、Safari的最新版都支持打印網頁到PDF，Edge未測試。</p>
<p>優點：</p>
<ol>
<li>實現成本低。</li>
</ol>
<p>缺點：</p>
<ol>
<li>用戶體驗差。</li>
</ol>
<h3 id="導出word文檔"><a href="#導出word文檔" class="headerlink" title="導出word文檔"></a>導出word文檔</h3><p>優點：</p>
<ol>
<li>實現成本低。（未證實）</li>
</ol>
<p>缺點：</p>
<ol>
<li>用戶可更改文檔。</li>
</ol>
<h2 id="參考"><a href="#參考" class="headerlink" title="參考"></a>參考</h2><ul>
<li><a href="https://blog.stahlmandesign.com/export-html-to-pdf-how-hard-can-it-be/" target="_blank" rel="external">https://blog.stahlmandesign.com/export-html-to-pdf-how-hard-can-it-be/</a></li>
<li><a href="https///my.oschina.net/janpoem/blog/705912">PHP輸出PDF打印HTML5+CSS3打印格式控制(Prince和wkhtmltopdf)</a></li>
</ul>
]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;結論&quot;&gt;&lt;a href=&quot;#結論&quot; class=&quot;headerlink&quot; title=&quot;結論&quot;&gt;&lt;/a&gt;結論&lt;/h2&gt;&lt;p&gt;傾向於通過wkhtmltopdf+消息隊列實現。&lt;/p&gt;
&lt;p&gt;工作流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用戶保存表單&lt;/li&gt;
&lt;li&gt;推送生
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="編程" scheme="http://0x3f.org/tags/%E7%B7%A8%E7%A8%8B/"/>
    
      <category term="PHP" scheme="http://0x3f.org/tags/php/"/>
    
  </entry>
  
  <entry>
    <title>少不讀村上</title>
    <link href="http://0x3f.org/post/after-reading-killing-commendatore/"/>
    <id>http://0x3f.org/post/after-reading-killing-commendatore/</id>
    <published>2018-04-22T05:55:00.000Z</published>
    <updated>2018-11-04T04:35:09.996Z</updated>
    
    <content type="html"><![CDATA[<p>讀完了《刺殺騎士團長》。</p>
<p>開始一直以為是類似《禁閉島》那樣的表達手法，覺得當個懸疑的故事看也不錯，結果直到最後一頁，才發現連裝神弄鬼都不是，頓時覺得六十塊錢花得有點冤。單從表達手法上說，不喜歡神神叨叨的東西。憑著炒魔幻現實主義的冷飯得諾獎怕是不大可能。</p>
<p>故事的大致情節是：生活平淡的畫家，突遇婚變，逃避現實的過程中經歷一系列魔幻和現實交錯的事，最後解開心結，回到現實，找到救贖。</p>
<p>這本書要表達的東西很多，出現的每一個主體都存在於多條敘事線中，只粗略讀過一遍，大概也就理解了個皮毛。最主要的，是兩個概念和五幅畫。</p>
<p>兩個概念，分別是「理念」和「隱喻」。</p>
<p>理念是人在自我審視下出現的另一個「我」，包括善的和惡的。象徵善的理念的是「騎士團長」，一個時隱時現、身高60釐米的古代日本武士形象。象徵惡的理念的是「白色斯巴魯男子」，隨時提醒「我」：你的惡，我都知道。</p>
<p>隱喻是人生各種經歷的具象化的形象。</p>
<p>五幅畫，分別是《刺殺騎士團長》、《免色肖像畫》、《白色斯巴魯男子》、《雜木林中的洞穴》和《真理惠肖像畫》。</p>
<p>《刺殺騎士團長》的作用很多。首先，從這幅畫引出被遺忘的二戰中的往事，包括雨田具彥在奧地利和雨田繼彥在南京的遭遇。其次，騎士團長於「我」，是善的理念的象徵，於雨田具彥，是隱藏數十年揮之不去的心結。第三，最終「我」刺殺了騎士團長，一方面解了雨田具彥的心結，使其安詳地離世，另一方面，這是「我」進入隱喻世界的前提，也是解救真理惠的必要條件。</p>
<p>《白色斯巴魯男子》象徵「我」的惡的理念，也是所有人的惡的理念。</p>
<p>《免色肖像畫》引出免色這個重要角色。免色是個從世俗的各方面看都臻於完美的男人，然而這幅畫真正打動他的，恰恰是表現出了那些深藏的、消極的、惡的不完美的東西。</p>
<p>《雜木林中的洞穴》既是魔幻的開端，也是魔幻的終點。一切魔幻的開始，源於深夜中聽到的鈴聲。而「我」穿過隱喻世界，逃回現實世界，也發生在這個洞里。</p>
<p>《真理惠肖像畫》。真理惠既是「我」的妹妹「路」的替身，也是免色的心結。「我」通過刺殺騎士團長、穿過隱喻世界「解救」了真理惠，實際上解開了對「路」早逝的心結。</p>
<p>很多年前讀過《挪威的森林》，沮喪得要命，那時就認為少不讀村上春樹，至今如故。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;讀完了《刺殺騎士團長》。&lt;/p&gt;
&lt;p&gt;開始一直以為是類似《禁閉島》那樣的表達手法，覺得當個懸疑的故事看也不錯，結果直到最後一頁，才發現連裝神弄鬼都不是，頓時覺得六十塊錢花得有點冤。單從表達手法上說，不喜歡神神叨叨的東西。憑著炒魔幻現實主義的冷飯得諾獎怕是不大可能。&lt;/p&gt;
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="讀書" scheme="http://0x3f.org/tags/%E8%AE%80%E6%9B%B8/"/>
    
  </entry>
  
  <entry>
    <title>鼠須管的美化</title>
    <link href="http://0x3f.org/post/beautify-squrrel-input-method/"/>
    <id>http://0x3f.org/post/beautify-squrrel-input-method/</id>
    <published>2018-04-21T12:52:42.000Z</published>
    <updated>2018-11-04T04:35:10.153Z</updated>
    
    <content type="html"><![CDATA[<p>效果如下：<br><img src="https://ws2.sinaimg.cn/large/006tNbRwly1fwvx9h8tgtj30n20bqaah.jpg" alt="Ulysses_2018-04-21 20-43-42@2x"></p>
<p>儘管鼠須管的Github倉庫一直在更新，但釋出版已經很久沒有更新了，所以下面的美化基於網絡上個人編譯的版本。<a href="https://scomper.me/gtd/-shu-xu-guan-de-diao-jiao-bi-ji" target="_blank" rel="external">這篇文章</a>里有該版本和「花園明朝」字體的下載鏈接，按照文中的說明替換鼠須管的程序。（<em>注意：官方當前釋出版本鼠須管不支持下文通過patch自定義配置的方式，會造成原配置信息丟失。也不支持圖示的樣式。</em>）</p>
<p>然後參考<a href="https://scomper.me/gtd/shu-xu-guan-shu-ru-fa-de-xin-pei-se" target="_blank" rel="external">這篇文章</a>，把新的顏色方案移植到用戶配置中。</p>
<p>圖示樣式使用「dust」方案。原色彩方案的字體設置的有點小，需要把font_point和label_font_point分別從14和10修改成18和14。原方案的第一順序字體是「HYQiHei-55S Book」，要使用圖示的花園明朝字體，可以不安裝或者從配置信息中去掉該字體。由於原方案中已存在的配置項不能通過patch的方式覆蓋，所以只能直接修改squirrel.yaml文件。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;效果如下：&lt;br&gt;&lt;img src=&quot;https://ws2.sinaimg.cn/large/006tNbRwly1fwvx9h8tgtj30n20bqaah.jpg&quot; alt=&quot;Ulysses_2018-04-21 20-43-42@2x&quot;&gt;&lt;/p&gt;
&lt;p&gt;儘管鼠須管的
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="工具" scheme="http://0x3f.org/tags/%E5%B7%A5%E5%85%B7/"/>
    
      <category term="軟件" scheme="http://0x3f.org/tags/%E8%BB%9F%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>我在用的Safari擴展</title>
    <link href="http://0x3f.org/post/the-safari-extensions-i-am-using/"/>
    <id>http://0x3f.org/post/the-safari-extensions-i-am-using/</id>
    <published>2018-04-15T14:29:10.000Z</published>
    <updated>2018-11-04T04:35:09.870Z</updated>
    
    <content type="html"><![CDATA[<p>和Chrome相比，Safari更省電、需要更少的系統資源，而且Chrome還有一些莫名其妙的問題，比如在沒有運行的時候，從Alfred執行搜索會啓動兩個窗口，一個是之前的會話，另一個是當前的搜索頁面。並且，啓用了一些擴展之後Safari的體驗可以改進很多。所以平時用Safari更多一些。</p>
<h2 id="sVim"><a href="#sVim" class="headerlink" title="sVim"></a>sVim</h2><p>作為注重效率的Vim黨和鍵盤黨，這種擴展是使用任何瀏覽器必備的東西。最常用的就是用標記打開鏈接的功能。</p>
<h2 id="Tampermonkey"><a href="#Tampermonkey" class="headerlink" title="Tampermonkey"></a>Tampermonkey</h2><p>油猴腳本管理器，應該是任何瀏覽器必備的東西。</p>
<h2 id="AutoPagerize"><a href="#AutoPagerize" class="headerlink" title="AutoPagerize"></a>AutoPagerize</h2><p>用Google搜索時自動滾動到下一頁。</p>
<h2 id="RSS-Menu"><a href="#RSS-Menu" class="headerlink" title="RSS Menu"></a>RSS Menu</h2><p>當發現當前頁面有可訂閱的RSS鏈接時，在工具欄圖標上顯示提示。</p>
<h2 id="Instapaper"><a href="#Instapaper" class="headerlink" title="Instapaper"></a>Instapaper</h2><p>稍後讀工具。</p>
<h2 id="Turn-Off-the-Lights"><a href="#Turn-Off-the-Lights" class="headerlink" title="Turn Off the Lights"></a>Turn Off the Lights</h2><p>看視頻時降低網頁其餘部分亮度。</p>
<h2 id="Scroll-To-Top-Button"><a href="#Scroll-To-Top-Button" class="headerlink" title="Scroll To Top Button"></a>Scroll To Top Button</h2><p>在頁面右下角顯示一個浮動的跳轉到頁首按鈕。</p>
<h2 id="Push-for-Kindle"><a href="#Push-for-Kindle" class="headerlink" title="Push for Kindle"></a>Push for Kindle</h2><p>FiveFilters.org的發送到Kindle按鈕。</p>
<h2 id="octotree"><a href="#octotree" class="headerlink" title="octotree"></a>octotree</h2><p>GitHub側邊欄。</p>
<h2 id="Translate"><a href="#Translate" class="headerlink" title="Translate"></a>Translate</h2><p>翻譯當前頁。</p>
<h2 id="WikiWand"><a href="#WikiWand" class="headerlink" title="WikiWand"></a>WikiWand</h2><p>優化維基百科閱讀體驗。</p>
<h2 id="Xdebug-Helper"><a href="#Xdebug-Helper" class="headerlink" title="Xdebug Helper"></a>Xdebug Helper</h2><p>PHP單步調試輔助工具。</p>
<h2 id="AdBlock"><a href="#AdBlock" class="headerlink" title="AdBlock"></a>AdBlock</h2><p>廣告過濾器。</p>
<h2 id="Sessions"><a href="#Sessions" class="headerlink" title="Sessions"></a>Sessions</h2><p>網頁會話管理器。如果打開的頁面太多，又可能在將來再用到，可以保存會話後清理掉，用到的時候再打開保存過的會話。雖然沒有Chrome下的Session Buddy和Tab Snooze好用，但是解決關鍵問題也夠了。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;和Chrome相比，Safari更省電、需要更少的系統資源，而且Chrome還有一些莫名其妙的問題，比如在沒有運行的時候，從Alfred執行搜索會啓動兩個窗口，一個是之前的會話，另一個是當前的搜索頁面。並且，啓用了一些擴展之後Safari的體驗可以改進很多。所以平時用Saf
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="工具" scheme="http://0x3f.org/tags/%E5%B7%A5%E5%85%B7/"/>
    
      <category term="瀏覽器" scheme="http://0x3f.org/tags/%E7%80%8F%E8%A6%BD%E5%99%A8/"/>
    
      <category term="軟件" scheme="http://0x3f.org/tags/%E8%BB%9F%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>廣告過濾工具AdBlock、Adblock Plus和uBlock的簡單對比</title>
    <link href="http://0x3f.org/post/a-simple-comparison-among-adblock-ublock-and-adblock-plus/"/>
    <id>http://0x3f.org/post/a-simple-comparison-among-adblock-ublock-and-adblock-plus/</id>
    <published>2018-04-01T14:47:47.000Z</published>
    <updated>2018-11-04T04:35:10.176Z</updated>
    
    <content type="html"><![CDATA[<p>Adblock Plus作者的那篇博客可能會影響很多人。我並不關心那些情懷的東西，只看療效。</p>
<p>簡單地對比了下AdBlock、Adblock Plus、uBlock在Safari for Mac上的效果，所有樣本和環境均為當前最新版本。AdBlock開啓Safari內容過濾後是最好的，成功地過濾掉了我常訪問的一個BT下載網站上的所有廣告，而不開啓Safari內容過濾時，會出現部分廣告先顯示後隱藏的情況。uBlock漏掉了個別不容易屏蔽的。而Adblock Plus最差，缺省設置下一條都沒過濾掉，在選擇更多的過濾規則後才過濾掉一部分。由於樣本很單一，本結論不具有普適性。</p>
<p>說句題外話，我覺得Adblock Plus這名字起得動機就挺不純的，沒有詳細考證過，印象中這個東西是比AdBlock後出現的，而且這名字很容易讓人理解成AdBlock的加強版。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Adblock Plus作者的那篇博客可能會影響很多人。我並不關心那些情懷的東西，只看療效。&lt;/p&gt;
&lt;p&gt;簡單地對比了下AdBlock、Adblock Plus、uBlock在Safari for Mac上的效果，所有樣本和環境均為當前最新版本。AdBlock開啓Safa
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="軟件" scheme="http://0x3f.org/tags/%E8%BB%9F%E4%BB%B6/"/>
    
  </entry>
  
  <entry>
    <title>變形金剛真人電影系列被重置</title>
    <link href="http://0x3f.org/post/transformers-live-action-movie-series-reset/"/>
    <id>http://0x3f.org/post/transformers-live-action-movie-series-reset/</id>
    <published>2018-02-18T03:51:13.000Z</published>
    <updated>2018-11-04T04:35:09.984Z</updated>
    
    <content type="html"><![CDATA[<p>根據這條<a href="http://news.tfw2005.com/2018/02/16/transformers-cinematic-universe-current-movie-series-rebooted-358641" target="_blank" rel="external">消息</a>，變形金剛真人電影系列將會被新團隊重置，原定在明年的第6部被取消。也就是說，看完今年大黃蜂的電影後，2021年前都不會有變形金剛主題的新片了。</p>
<p>這種壯士斷腕的做法多少算是個好消息吧，經歷了變5的失敗，再讓麥克爾貝這麼折騰下去，變形金剛這個IP就完蛋了。</p>
<p>我對這件事是無可無不可的。作為一個八零後，我對變形金剛的情懷來自G1動畫，所以我的關注點主要是還原G1動畫風格的Master Piece系列。在MPM-3出來之前，我對電影系的玩具沒多大興趣。</p>
<p>當年變1上映的時候，我很難認同電影系的風格。但是後來從變1到變3，也逐漸地開始接受它，畢竟隨著技術的進步，審美風格也會發生變化，沒必要固守二、三十年前的東西。我對電影系最大的意見是劇情太爛，有句話很對，說一部戲好不好關鍵看反派角色，《蝙蝠俠之黑暗騎士崛起》之所以口碑不錯，主要是大反派小醜這個角色很立體。回頭說當年的G1動畫最成功的一點也是霸天虎尤其威震天這個角色塑造得比較成功。反觀電影系，相對於汽車人華麗的人形態和隱藏形態，霸天虎陣營就是一群猥瑣的低級生物，而且人物性格的塑造極其臉譜化。</p>
<p>直到後來變4的時候，風格進一步變化，加入大量騎士元素，機械元素的減少導致科技感進一步下降。最要命的是變4的玩具做得實在是一塌糊塗。至於變5，那真是電影做得和玩具一樣爛。</p>
<p>真是成也麥克爾貝，敗也麥克爾貝。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;根據這條&lt;a href=&quot;http://news.tfw2005.com/2018/02/16/transformers-cinematic-universe-current-movie-series-rebooted-358641&quot; target=&quot;_blank&quot; rel
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="隨筆" scheme="http://0x3f.org/tags/%E9%9A%A8%E7%AD%86/"/>
    
      <category term="變形金剛" scheme="http://0x3f.org/tags/%E8%AE%8A%E5%BD%A2%E9%87%91%E5%89%9B/"/>
    
  </entry>
  
  <entry>
    <title>iQunix F60使用感受</title>
    <link href="http://0x3f.org/post/iqunix-f60/"/>
    <id>http://0x3f.org/post/iqunix-f60/</id>
    <published>2018-02-17T07:40:47.000Z</published>
    <updated>2018-11-04T04:35:10.130Z</updated>
    
    <content type="html"><![CDATA[<p><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fwvx01vj5ej31kw0w04qq.jpg" alt="fullsizeoutput_392"></p>
<p>我不喜歡冗余的東西。如果桌子足夠大，我能接受的極限是87鍵。然而我的Filco 87聖手二代黑茶已經吃灰很久了，之前的主力是Poker II白青。所以目前主要的關注點還是在60鍵上。</p>
<p>我對Poker整體上還是比較滿意的，尤其是按鍵編程的功能很方便。但是有兩點讓我很不滿意。一是做工一般，鍵帽的活動幅度較大，遠遠沒有Filco的扎實感。二是不支持藍牙，無線化是一個用了就回不去的東西。</p>
<p>iQunix F60就是這麼個東西，符合我對鍵盤所有的核心需求：支持藍牙、做工好、60%佈局、Cherry軸、PBT鍵帽。用了一段時間，整體是滿意的。</p>
<p>買的銀白色，收到的是側刻，算是個小驚喜吧，雖然不如無刻騷氣，至少不像正刻那麼平庸。鋁合金外框加白色PBT鍵帽的顏值很高，整體很有質感。</p>
<p>做工比Poker好很多，找回了Filco的扎實感。PBT的鍵帽不打油，這一點超過了Filco。</p>
<p>續航一般，輕度使用可以持續一周。信號強度也很一般，一米的距離，已能感受到明顯的延遲。不過這些在實際的使用中不是什麼大問題。</p>
<p>功能上，不支持鍵盤編程，這點不如Poker。但是可以用組合鍵交換左側WIN鍵和ALT鍵，對Mac很友好。代替方向鍵的組合鍵位也比Poker合理。此外，可以用組合鍵切換有線和無線模式，支持在3台設備之間切換。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;img src=&quot;https://ws4.sinaimg.cn/large/006tNbRwly1fwvx01vj5ej31kw0w04qq.jpg&quot; alt=&quot;fullsizeoutput_392&quot;&gt;&lt;/p&gt;
&lt;p&gt;我不喜歡冗余的東西。如果桌子足夠大，我能接受的極限是8
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="數碼" scheme="http://0x3f.org/tags/%E6%95%B8%E7%A2%BC/"/>
    
  </entry>
  
  <entry>
    <title>異地補卡下的北京中年</title>
    <link href="http://0x3f.org/post/story-of-changing-sim-card/"/>
    <id>http://0x3f.org/post/story-of-changing-sim-card/</id>
    <published>2018-02-16T09:24:59.000Z</published>
    <updated>2018-11-04T04:35:10.004Z</updated>
    
    <content type="html"><![CDATA[<p>我媽的老SIM卡不能用在iPhone里。因為我的卡就是從大卡剪過來的，所以騎車轉了一大圈，臨近年關，大部分修手機的店、合作營業廳都關了，最後一個賣手機的店里的老闆說這種老卡不能剪，只能換卡。</p>
<p>之前聽附近移動營業廳里的大堂經理說，換卡需要機主本人、身份證和服務密碼，而且異地補卡只能去部分較大的營業廳。這個可以在網上營業廳里查到。</p>
<p>事先在網上營業廳重置了服務密碼。第二天一早，去了最近的可以異地補卡的營業廳。工作人員給了張紙條，讓寫下手機號、服務密碼，他們查了一下，說是鑒權失敗，讓第二天再去。留了營業廳的電話，事先讓他們查一下，確認可以辦了再去。</p>
<p>第三天早上十點，打電話過去，說是辦異地補卡的人還沒來。十一點再打過去，查了一下，說是可以辦了。去之前差點沒帶手機，因為感覺就是辦張卡，回來裝也一樣。事實證明，不帶會後悔。</p>
<p>補卡也需要用手寫板簽字和人臉識別，因為是2d圖像識別，所以很傻，需要搖頭、點頭、眨眼、張嘴，在張嘴這一步重試了很多次都失敗……</p>
<p>補的第一張卡插到手機里不能識別，第二張才成功。</p>
<p>總結以上，異地補卡需要注意這些點：</p>
<ul>
<li>本人、身份證、服務密碼（服務密碼可以去網上營業廳重置，前提是卡還在，還能接到短信）</li>
<li>去能辦理異地補卡的營業廳（可以在網上營業廳查詢，或者打客服電話）</li>
<li>不要去太早，最好事先打電話讓他們查一下，確認可以辦了再去</li>
<li>一定要帶手機和開卡槽的工具，現場裝卡測試</li>
</ul>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;我媽的老SIM卡不能用在iPhone里。因為我的卡就是從大卡剪過來的，所以騎車轉了一大圈，臨近年關，大部分修手機的店、合作營業廳都關了，最後一個賣手機的店里的老闆說這種老卡不能剪，只能換卡。&lt;/p&gt;
&lt;p&gt;之前聽附近移動營業廳里的大堂經理說，換卡需要機主本人、身份證和服務密
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="隨筆" scheme="http://0x3f.org/tags/%E9%9A%A8%E7%AD%86/"/>
    
  </entry>
  
  <entry>
    <title>飛利浦電動牙刷HX9903/42使用感受</title>
    <link href="http://0x3f.org/post/philips-hx9903-42/"/>
    <id>http://0x3f.org/post/philips-hx9903-42/</id>
    <published>2018-02-10T09:23:15.000Z</published>
    <updated>2018-11-04T04:35:09.976Z</updated>
    
    <content type="html"><![CDATA[<p>效果雖說沒別人說的誇張，也的確刷得很乾淨，再就是緩解了胳膊的疲勞感。</p>
<p>有個問題。剛開始的幾天，雖然電池已經充滿，但是震動強度很一般，而且手柄底部的壓力警示燈一直閃，試過拔掉刷頭，問題還在，說明是手柄的問題。直到提示電量緊張後第二次充電，之後才恢復正常。</p>
<p>App、多種刷頭、多種模式、壓力警示和三級震動強度都是噱頭，刷個牙而已，HX6730足夠了，多交的幾百塊錢除了智商稅，也就顏值和無線充電有點價值了。</p>
<p>電動牙刷不是個用了就回不去的東西，不過體驗確實很好，刷牙不再是例行公事和負擔，而是件挺有意思的事。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;效果雖說沒別人說的誇張，也的確刷得很乾淨，再就是緩解了胳膊的疲勞感。&lt;/p&gt;
&lt;p&gt;有個問題。剛開始的幾天，雖然電池已經充滿，但是震動強度很一般，而且手柄底部的壓力警示燈一直閃，試過拔掉刷頭，問題還在，說明是手柄的問題。直到提示電量緊張後第二次充電，之後才恢復正常。&lt;/p&gt;
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="數碼" scheme="http://0x3f.org/tags/%E6%95%B8%E7%A2%BC/"/>
    
      <category term="器物" scheme="http://0x3f.org/tags/%E5%99%A8%E7%89%A9/"/>
    
  </entry>
  
  <entry>
    <title>用OTP Auth替換了Authy</title>
    <link href="http://0x3f.org/post/migrate-from-authy-to-otp-auth/"/>
    <id>http://0x3f.org/post/migrate-from-authy-to-otp-auth/</id>
    <published>2018-02-06T14:53:40.000Z</published>
    <updated>2018-11-04T04:35:09.964Z</updated>
    
    <content type="html"><![CDATA[<p>Authy的界面很花哨，但並不實用，管理多個兩步驗證賬號時查詢效率很低。OTP Auth採用更直觀的列表佈局，並且支持搜索，在用戶體驗和效率上有更大的優勢。兩者之間沒有批量遷移數據的方式，只能逐個手動添加，很麻煩。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Authy的界面很花哨，但並不實用，管理多個兩步驗證賬號時查詢效率很低。OTP Auth採用更直觀的列表佈局，並且支持搜索，在用戶體驗和效率上有更大的優勢。兩者之間沒有批量遷移數據的方式，只能逐個手動添加，很麻煩。&lt;/p&gt;

    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="安全" scheme="http://0x3f.org/tags/%E5%AE%89%E5%85%A8/"/>
    
  </entry>
  
  <entry>
    <title>對XSS的防禦更適合放在前端</title>
    <link href="http://0x3f.org/post/better-to-do-defenses-against-xss-in-front-end/"/>
    <id>http://0x3f.org/post/better-to-do-defenses-against-xss-in-front-end/</id>
    <published>2018-02-06T07:13:17.000Z</published>
    <updated>2018-11-04T04:35:10.016Z</updated>
    
    <content type="html"><![CDATA[<p>很多項目會把轉義操作放在後端接口獲取參數的地方，從而忽略了這樣一個問題——為什麼主流框架都不在獲取參數的方法里實現這一點？</p>
<p>以Laravel為例，如果可以這樣獲取轉義後的參數：<code>$request-&gt;escape(&#39;content&#39;)</code>，代碼會顯得更優雅，而實際上只能用自己封裝的函數手工轉義：<code>my_escape($request-&gt;get(&#39;content&#39;))</code>，很醜陋的代碼。</p>
<p>事實上，主流框架並非沒有提供防禦XSS的封裝，只是都放在模板引擎里。這樣做的依據是，XSS的原理是在原本用於展示的數據里包含了可執行的文本，但不是所有展示的位置都不應該包含可執行的文本。從另一角度上說，後端應該校驗前端傳遞的數據，但不應該篡改它。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;很多項目會把轉義操作放在後端接口獲取參數的地方，從而忽略了這樣一個問題——為什麼主流框架都不在獲取參數的方法里實現這一點？&lt;/p&gt;
&lt;p&gt;以Laravel為例，如果可以這樣獲取轉義後的參數：&lt;code&gt;$request-&amp;gt;escape(&amp;#39;content&amp;#39
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="編程" scheme="http://0x3f.org/tags/%E7%B7%A8%E7%A8%8B/"/>
    
      <category term="架構" scheme="http://0x3f.org/tags/%E6%9E%B6%E6%A7%8B/"/>
    
  </entry>
  
  <entry>
    <title>十公里租房補貼是個天才的福利制度</title>
    <link href="http://0x3f.org/post/rent-subsides-within-10km-is-wise/"/>
    <id>http://0x3f.org/post/rent-subsides-within-10km-is-wise/</id>
    <published>2018-02-06T03:12:23.000Z</published>
    <updated>2018-11-04T04:35:10.018Z</updated>
    
    <content type="html"><![CDATA[<p>十公里以內是個很適合通勤的距離，以任何一種公共交通方式都可以把時間控制在半小時左右。</p>
<p>通勤時間每增加半小時，生活質量都會下降一個量級，而生活質量是會直接影響一個人的工作質量和穩定性的。所以有些公司有十公里內租房補貼的福利，這項制度天才的地方在於，如果把這些補貼以工資的形式發放，員工可能仍然會因為住得遠導致幸福感很差，所以增加了很多不穩定的因素。這項制度間接地強制員工把自己收入的一部分用在提高自己生活質量上面，記得那個朝三暮四、朝四暮三的故事嗎？公司花同樣的錢，卻得到了更大的價值。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;十公里以內是個很適合通勤的距離，以任何一種公共交通方式都可以把時間控制在半小時左右。&lt;/p&gt;
&lt;p&gt;通勤時間每增加半小時，生活質量都會下降一個量級，而生活質量是會直接影響一個人的工作質量和穩定性的。所以有些公司有十公里內租房補貼的福利，這項制度天才的地方在於，如果把這些補貼
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="隨筆" scheme="http://0x3f.org/tags/%E9%9A%A8%E7%AD%86/"/>
    
  </entry>
  
  <entry>
    <title>癸醜望，月有食之</title>
    <link href="http://0x3f.org/post/lunar-eclipse/"/>
    <id>http://0x3f.org/post/lunar-eclipse/</id>
    <published>2018-01-31T15:54:41.000Z</published>
    <updated>2018-11-04T04:35:09.985Z</updated>
    
    <content type="html"><![CDATA[<p>大概這是我第一次看月全食，暗紅色，挺大個兒，但是拍出來就顯得很小。論效果，iPhone X還不如幾年前的LX5。</p>
<p><img src="https://ws2.sinaimg.cn/large/006tNbRwly1fwvwx762p5j31kw16oe82.jpg" alt="P1030593"><br><img src="https://ws4.sinaimg.cn/large/006tNbRwly1fwvwx920e1j31kw16o4qq.jpg" alt="P1030594"></p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;大概這是我第一次看月全食，暗紅色，挺大個兒，但是拍出來就顯得很小。論效果，iPhone X還不如幾年前的LX5。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ws2.sinaimg.cn/large/006tNbRwly1fwvwx762p5j31kw16oe82.j
    
    </summary>
    
      <category term="青梅煮酒" scheme="http://0x3f.org/categories/%E9%9D%92%E6%A2%85%E7%85%AE%E9%85%92/"/>
    
    
      <category term="隨筆" scheme="http://0x3f.org/tags/%E9%9A%A8%E7%AD%86/"/>
    
      <category term="圖片" scheme="http://0x3f.org/tags/%E5%9C%96%E7%89%87/"/>
    
  </entry>
  
  <entry>
    <title>解決Laravel的Facade在被Mock時不自動注入依賴的一種方法</title>
    <link href="http://0x3f.org/post/manual-dependency-injection-with-laravel/"/>
    <id>http://0x3f.org/post/manual-dependency-injection-with-laravel/</id>
    <published>2018-01-30T07:41:16.000Z</published>
    <updated>2018-11-04T04:35:10.026Z</updated>
    
    <content type="html"><![CDATA[<p>由於集成了Mockery，Laravel的Facade對單元測試非常友好，只需要一行代碼就能實現mocking。</p>
<p>例如，測試目標方法中調用了訂單工具類的一個方法，在使用依賴注入的方式時，需要用三行代碼實現對這個方法的mocking：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">$fakeOrderTool = m::mock(\App\Tool\Order::class);</div><div class="line">$fakeOrderTool-&gt;shouldReceive(<span class="string">'getById'</span>)-&gt;once()-&gt;with($id)-&gt;andReturn($fakeOrder);</div><div class="line"><span class="keyword">$this</span>-&gt;app-&gt;instance(\App\Tool\Order::class, $fakeOrderTool);</div></pre></td></tr></table></figure>
<p>而用Facade是這樣的：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">OrderFacade::shouldReceive(<span class="string">'getById'</span>)-&gt;once()-&gt;with($id)-&gt;andReturn($fakeOrder);</div></pre></td></tr></table></figure>
<p>當測試目標方法也屬於訂單工具類時，需要部分mock這個類，所以還要加上一行：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">OrderFacade::makePartial();</div></pre></td></tr></table></figure>
<p>但如果訂單工具類的構造方法里有需要注入的依賴關係，這里並不會被執行。所以我在工具類基類里封裝了一個方法，用反射機制實現手工注入依賴關係：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/**</span></div><div class="line"> * 注入依赖，用于单元测试</div><div class="line"> *</div><div class="line"> * <span class="doctag">@return</span>  void</div><div class="line"> * <span class="doctag">@author</span>  donieli</div><div class="line"> * <span class="doctag">@since</span>   5</div><div class="line"> * <span class="doctag">@version</span> 5</div><div class="line"> */</div><div class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">injectDependencies</span><span class="params">()</span></span></div><div class="line">&#123;</div><div class="line">    $reflector = <span class="keyword">new</span> \ReflectionClass(get_class(<span class="keyword">$this</span>));</div><div class="line">    $params    = $reflector-&gt;getConstructor()-&gt;getParameters();</div><div class="line">    $args      = [];</div><div class="line">    <span class="keyword">foreach</span> ($params <span class="keyword">as</span> $param) &#123;</div><div class="line">        $paramClass = $param-&gt;getClass();</div><div class="line">        <span class="keyword">if</span> (<span class="keyword">empty</span>($paramClass)) &#123;</div><div class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> \<span class="keyword">Exception</span>(<span class="string">'Dependency named '</span>.$param-&gt;getName().<span class="string">' cannot be injected.'</span>);</div><div class="line">        &#125;</div><div class="line">        $instance  = app()-&gt;make($paramClass-&gt;getName());</div><div class="line">        $args[] = $instance;</div><div class="line">    &#125;</div><div class="line">    call_user_func_array([<span class="keyword">$this</span>, <span class="string">'__construct'</span>], $args);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>然後就可以這樣處理：</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">OrderFacade::shouldReceive(<span class="string">'getById'</span>)-&gt;with($id)-&gt;once()-&gt;andReturn($fakeOrder);</div><div class="line">OrderFacade::makePartial();</div><div class="line">OrderFacade::injectDependencies();</div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;由於集成了Mockery，Laravel的Facade對單元測試非常友好，只需要一行代碼就能實現mocking。&lt;/p&gt;
&lt;p&gt;例如，測試目標方法中調用了訂單工具類的一個方法，在使用依賴注入的方式時，需要用三行代碼實現對這個方法的mocking：&lt;/p&gt;
&lt;figure c
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="編程" scheme="http://0x3f.org/tags/%E7%B7%A8%E7%A8%8B/"/>
    
      <category term="php" scheme="http://0x3f.org/tags/php/"/>
    
      <category term="laravel" scheme="http://0x3f.org/tags/laravel/"/>
    
  </entry>
  
  <entry>
    <title>從Vultr新加坡遷移到洛杉磯</title>
    <link href="http://0x3f.org/post/migrate-vultr-from-singapore-to-los-angeles/"/>
    <id>http://0x3f.org/post/migrate-vultr-from-singapore-to-los-angeles/</id>
    <published>2018-01-28T06:15:57.000Z</published>
    <updated>2018-11-04T04:35:09.969Z</updated>
    
    <content type="html"><![CDATA[<p>Vultr新加坡節點掛了兩天了，不能翻牆簡直什麼都乾不了。早上用CloudSpeed看了下，洛杉磯機房的響應速度還不錯，就遷移了過去。</p>
<h2 id="ShadowsocksR"><a href="#ShadowsocksR" class="headerlink" title="ShadowsocksR"></a>ShadowsocksR</h2><p>這個很簡單，用<a href="https://github.com/91yun/shadowsocks_install" target="_blank" rel="external">一鍵安裝腳本</a>。</p>
<h2 id="網絡加速"><a href="#網絡加速" class="headerlink" title="網絡加速"></a>網絡加速</h2><p>用BBR，<a href="https://teddysun.com/489.html" target="_blank" rel="external">一鍵安裝腳本</a>。</p>
<h2 id="Tiny-Tiny-RSS"><a href="#Tiny-Tiny-RSS" class="headerlink" title="Tiny Tiny RSS"></a>Tiny Tiny RSS</h2><p>先按照之前的<a href="/post/ttrss/">筆記</a>安裝ttrss。</p>
<p>然後重建一個空的ttrss的數據庫：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker <span class="built_in">exec</span> f6d92ad8efba /usr/bin/psql -c <span class="string">"drop database ttrss"</span></div><div class="line">docker <span class="built_in">exec</span> f6d92ad8efba /usr/bin/psql -c <span class="string">"create database ttrss"</span></div></pre></td></tr></table></figure>
<p>把數據庫的備份複製到容器里並導入：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker cp ttrss.sql f6d92ad8efba:/tmp/ttrss.sql</div><div class="line">docker <span class="built_in">exec</span> f6d92ad8efba /usr/bin/psql -d ttrss -f /tmp/ttrss.sql postgres</div></pre></td></tr></table></figure>
<p>以root身份登錄容器並刪除備份文件：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">docker <span class="built_in">exec</span> -it --user root f6d92ad8efba /bin/sh</div><div class="line">rm /tmp/ttrss.sql</div></pre></td></tr></table></figure>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Vultr新加坡節點掛了兩天了，不能翻牆簡直什麼都乾不了。早上用CloudSpeed看了下，洛杉磯機房的響應速度還不錯，就遷移了過去。&lt;/p&gt;
&lt;h2 id=&quot;ShadowsocksR&quot;&gt;&lt;a href=&quot;#ShadowsocksR&quot; class=&quot;headerlink&quot; 
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="筆記" scheme="http://0x3f.org/tags/%E7%AD%86%E8%A8%98/"/>
    
  </entry>
  
  <entry>
    <title>Unlox：兼顧安全和體驗的東西深得我心</title>
    <link href="http://0x3f.org/post/unlox/"/>
    <id>http://0x3f.org/post/unlox/</id>
    <published>2018-01-14T08:52:11.000Z</published>
    <updated>2018-11-04T04:35:09.883Z</updated>
    
    <content type="html"><![CDATA[<p>買了Unlox。早就知道MacID，陰差陽錯一直沒買，所以這又是一次後知後覺的行為。</p>
<p>曾經用過一段時間ControlPlane，通過多種條件自動判斷場景以啓用或關閉鎖屏密碼。後來在一次系統升級之後就不能用了。因為這個東西本身體驗也不是很好，免費的東西折騰起來太耗費精力，所以付費買體驗也是個不錯的選擇。</p>
<p>有三個功能對我來說很有用。</p>
<p>首先是用Face ID解鎖Mac。在Mac被喚醒後，iPhone X自動彈出解鎖的通知，點擊後Unlox被打開並自動調用Face ID，驗證通過後Mac即被解鎖。不過兩次Face ID驗證稍顯繁瑣，如果在iPhone鎖屏界面驗證通過後就自動解鎖，體驗會更好。不過我猜應該是iOS在這個地方不會通知到App。</p>
<p>其次是Tap解鎖。用手指點擊觸摸板，點擊次數和每次用的手指數目可以自定義。這個方式確實很方便。為了加強安全性，還可以設置當手機斷開時禁用Tap解鎖。</p>
<p>第三是離開時自動鎖屏。可以設置當手機和Mac之間的藍牙連接信號減弱多少時自動鎖屏。雖然對於Macbook用處不大，也不失為忘記合上屏幕時的一種補救手段。</p>
<p>此外還有其它一些功能，例如通過手機鎖定或解鎖Mac、靠近時自動喚醒Mac等。</p>
<p>今年Apple應該會全系支持Face ID，所以這只是一個過渡方案。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;買了Unlox。早就知道MacID，陰差陽錯一直沒買，所以這又是一次後知後覺的行為。&lt;/p&gt;
&lt;p&gt;曾經用過一段時間ControlPlane，通過多種條件自動判斷場景以啓用或關閉鎖屏密碼。後來在一次系統升級之後就不能用了。因為這個東西本身體驗也不是很好，免費的東西折騰起來太
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
      <category term="app" scheme="http://0x3f.org/tags/app/"/>
    
  </entry>
  
  <entry>
    <title>密碼管理的最佳實踐</title>
    <link href="http://0x3f.org/post/the-best-practice-of-password-management/"/>
    <id>http://0x3f.org/post/the-best-practice-of-password-management/</id>
    <published>2017-12-27T09:26:17.000Z</published>
    <updated>2018-11-04T04:35:09.956Z</updated>
    
    <content type="html"><![CDATA[<p>通密之所以不應該被過分指責，是因為有其存在的道理，沒有哪種方案的管理成本比它更低，它不需要購買昂貴的1password，不需要擔心臨時用的時候突然想不起來，而且，只要這個密碼足夠強壯並且使用環境足夠安全，大多數情況下也不會有什麼問題。通密的問題在於它的風險成本太高，一旦一處洩漏，所有使用這個密碼的地方都不安全。</p>
<p>另一個極端是，使用很複雜的密碼，每個賬號都不同，甚至用密碼生成工具生成完全沒有規律的隨機字符串。這種方案的安全性很高，高到連你自己都記不住。</p>
<p>所以我需要這樣一套好的方案，它應該在安全性和易用性之間取得一個比較好的平衡，並且隨著方法論和工具鏈的進化，這個平衡可以無限逼近黃金分割點。</p>
<p>首先，密碼應該是複雜但容易記住的。密碼的複雜度和記憶負擔並不成正比，例如如果你實在記不住“ppnn13%,dkstFeb1st”，那麼這樣呢——“娉娉裊裊十三余，豆蔻梢頭二月初”。密碼只是一個字符串，如果不去死記最終的值，而是字符串背後的規律，記憶的壓力就會小很多。</p>
<p>但考慮到每個賬號都想一個這樣的密碼是不現實的，而且怎麼解決記憶密碼和賬號的對應關係的問題？所以進一步，可以用這樣的密碼當前綴，每個密碼的前綴都一樣，然後針對每個賬號創造一個後綴，這個後綴應該是每個賬號都不同的，且和賬號有某種只有你自己才知道的關聯，這樣你可以隨時根據賬號計算出它的後綴。例如，可以用賬號拼音首字母（<em>當然，實際的規則應該更複雜一點</em>）。</p>
<p>這樣你就有了足夠複雜、每個賬號都不同並且很容易記住的密碼。進一步地，在私有設備上可以利用文本替換功能（<em>例如：Alfred for Mac的Snippets功能</em>）快速輸入通用前綴，某些支持按鍵編程的機械鍵盤會有更好的體驗。</p>
<p>不過好記性不如爛筆頭，為防萬一，還是需要一個Plan B。主流的密碼管理工具主要有這麼幾種：</p>
<ul>
<li>瀏覽器的賬號記憶功能</li>
<li>操作系統的keychain</li>
<li>在線密碼管理工具</li>
<li>離線密碼管理工具</li>
</ul>
<p>瀏覽器一般是把密碼以明文存儲在本地的，firefox雖然有個主密碼，但只是個幌子，別人仍然可以拿到它記錄密碼的數據庫文件。這種做法的邏輯在於，設備上存儲的數據的安全性由操作系統和用戶負責，換句話說，用戶不應該允許他人用自己的權限登錄設備。但實際上很難避免這種情況，而且還要考慮到系統被入侵的可能。所以，只應該讓瀏覽器記住那些最不重要的賬號。</p>
<p>相對來說，操作系統的keychain一般有自動鎖定的功能，會更安全一些。但是仍無法完全避免上述問題。而且keychain只能記錄賬號和密碼，無法存儲更多的附加信息。所以這種工具也只應該存儲一些不重要的賬號。</p>
<p>最著名的在線密碼管理工具應該是Lastpass。關於它的安全性有很多種說法，不過我覺得但凡是敏感數據都不要存儲到線上，所以這種方式不予考慮。</p>
<p>我傾向於使用離線的密碼管理工具。1password據說很好用，但是太貴了，而且開源免費的keepass已經完全夠用了。我在Mac上用KeePassXC，在iOS中用MiniKeePass，私鑰文件離線存儲，然後數據庫文件用Dropbox同步就可以了。</p>
<p>此外，對於重要的賬號，如果支持兩步驗證，一定要開啓，然後用OTP Auth管理即可。</p>
<p>最終的方案是：</p>
<ul>
<li>方法論：統一的複雜但有規律的前綴+根據賬號計算出來的後綴</li>
<li>工具鏈：KeePass + OTP Auth + Dropbox</li>
</ul>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;通密之所以不應該被過分指責，是因為有其存在的道理，沒有哪種方案的管理成本比它更低，它不需要購買昂貴的1password，不需要擔心臨時用的時候突然想不起來，而且，只要這個密碼足夠強壯並且使用環境足夠安全，大多數情況下也不會有什麼問題。通密的問題在於它的風險成本太高，一旦一處
    
    </summary>
    
      <category term="計算機" scheme="http://0x3f.org/categories/%E8%A8%88%E7%AE%97%E6%A9%9F/"/>
    
    
      <category term="最佳實踐" scheme="http://0x3f.org/tags/%E6%9C%80%E4%BD%B3%E5%AF%A6%E8%B8%90/"/>
    
  </entry>
  
</feed>
