在Apache環境下為網頁資料夾加密

學習網頁開發的時候,難免會需要自行架設伺服器在本機上,但一旦為自己的電腦安裝了伺服器之後,只要電腦一連上網,全世界任何人只要使用你在網路上的IP就可以連上你的伺服器。

於是我們想要設定使用者名稱與密碼來保護我們自己的伺服器,以限定能夠瀏覽的使用者。而為了做到這件事,我們會需要兩個檔案:.htpasswd、與.htaccess

為伺服器新增使用者

首先我們需要產生一個存放帳號密碼的.htpasswd檔案,建議是放在網頁根目錄再上層的其他地方以避免他人從網路上存取。

例如要新增的使用者名稱叫做user,產生方法如下。

sudo htpasswd -c /path/to/.htpasswd user

此時系統會提示你要輸入密碼,Enter確定後會要再輸入一次,以確保剛剛輸入密碼正確。

如果你想繼續增加一個使用者叫做user2,可以在終端機再這樣輸入。

sudo htpasswd /path/to/.htpasswd user2

你可以為user2設定另一個完全不同的密碼。

.htpasswd檔案裡面,帳號會直接儲存、而密碼會記錄一個用MD5算出的雜湊值(看起來就是一個亂碼才不會被發現),所以我們看到剛剛做出來的.htpasswd檔案裡面寫成這樣:

user:$apr1$dxTa0IZA$B8XPOXcm5geDT17eJ2VYf1
user2:$apr1$lzxsIfXG$tmCvCfb49vpPFwKGVsuYz.

分別記錄兩個使用者(user與user2)的帳號與密碼雜湊值,之後伺服器就可以用同樣的算法去做密碼驗證。所以其實如果不用終端機的話,也可以到這個網站來產生我們想要的帳號與密碼雜湊值,一個使用者寫一行,或者你也可以自己寫演算法XD

保護根目錄

接著我們在想保護的資料夾裡面,新增一個.htaccess檔案寫入以下文字來告訴伺服器:這個目錄需要有權限才能進入,如果該檔案已經存在的話就直接把文字加在裡面。

AuthType Basic
AuthName "My Protected Area"
AuthUserFile /path/to/.htpasswd
Require valid-user

不知道怎麼寫的話,也可以到這個網站把產生的文字存成檔案,直接放在想保護的目錄裡就可以了。

弄好之後,再次進入我們自己的網站,搞定!

補充說明

.htaccess檔案內我們剛剛新增的內容,其實要寫在伺服器設定檔也是可以的,可以參考這個網誌

另外,如果想要修改密碼的話,其實就等於再做一次使用者設定,例如我們要修改user2的密碼。

sudo htpasswd /path/to/.htpasswd user2

參考資料

  1. DigitalOcean
  2. [教學]對網頁啟用密碼驗證 (Apache) | 辛比誌
  3. 對網頁目錄設定需要帳號密碼來登入 – htaccess @ 黃昏的甘蔗

在WordPress中將分類按照階層排列

目標

假設現在有一篇文章的分類包含以下多項,且彼此之間有階層關係。

  • 關東
    • 東京
      • 代官山
      • 澀谷
    • 神奈川
      • 橫濱

所以我們想要將這些分類,依照原本的階層順序顯示為:關東、東京、代官山、澀谷、神奈川、橫濱。在Wordpress中預設以name排序:代官山、東京、橫濱、澀谷、神奈川、關東,而其他比較有意義的排序法大概也就是按文章數量countquery查詢工具),但也並非想要的排列。

有些Plugin可以自訂分類排序,例如:

  • WP Term Order
  • Category Order and Taxonomy Terms Order
  • Custom Taxonomy Order

但是能夠改的排序,限為同層分類的排序,例如你可以把自訂把「澀谷」擺到「代官山」前面,或者讓「神奈川」整個群組都比「東京」先出現,依然不是我們要的功能。

只好來實做看看。

取得所有分類

首先要取得某篇文章的所選分類,可以用get_the_category來取得一個包含所有分類項目Object的Array,再利用array_map把這些分類的名稱單獨挑出來。

$object_id = get_the_ID();
$categories = get_the_category( $object_id );

$terms = implode( '、', array_map(function($item) { return $item->name; }, $categories ));
echo $terms; // 代官山、東京、橫濱、澀谷、神奈川、關東

或者,也可以使用wp_get_object_terms來取得任意自訂分類。

$object_id = get_the_ID();
$taxonomies = 'category'; // 這邊我們就選擇預設分類
$args = array( 'fields' => 'all' ); // options arguments
$categories = wp_get_object_terms( $object_id, $taxonomies, $args );

$terms = implode( '、', array_map(function($item) { return $item->name; }, $categories ));
echo $terms; // 代官山、東京、橫濱、澀谷、神奈川、關東

我們發現:欸?階層不見了,最上層的「關東」表示憤怒竟然排在最後!!!先不要管為什麼,但接下來我們就要利用分類項目中的parent屬性,來為每個項目進行認親的動作,以達到優先以階層排序的目的。

為分類找階層排序

懶得看文章的話程式碼在這裡,使用方法就是把wp_get_object_terms改成get_object_terms_hierarchical就可以惹。

<?php
// 點兩下這裡看原始碼
/**
  * Make terms retrieved by wp_get_object_terms() organized hierarchically.
  *
  * Use this function instead of wp_get_object_terms() to get a hierarchically
  * structured array or term data.
  *
  * This function takes the terms returned by wp_get_object_terms() and organizes
  * them into a hierarchical array with the parent's children (and grandchildren)
  * stored in nested arrays (within the 'children' item).
  *
  * @see wp_get_object_terms() for parameters.
  *
  * @return array $terms Hierarchilized $terms array.
  */
function get_object_terms_hierarchical( $object_ids, $taxonomies, $args = array() ) {
  $return_flat = true;
  $tree  = array();
  $terms = wp_get_object_terms( $object_ids, $taxonomies, $args );
  $ids = array_map(function($item) { return $item->term_id; }, $terms);
  if ( ! empty( $terms ) ) {
    foreach ( $terms as $term ) {
      if ( $term->parent == 0 || !in_array($term->parent, $ids) ) {
        if ( $return_flat ) {
          array_push($tree, $term);
          get_child_terms( $term->term_id, $terms, $tree );
        } else {
          $tree[ $term->term_id ] = $term;
          $tree[ $term->term_id ]->children = get_child_terms( $term->term_id, $terms );
        }
      }
    }
  }
      
  return $tree;
}
  
/**
 * Organizes the child terms.
  *
  * This is a recursive function.
  *
  * @param interval $parent_id The parent ID to retrieve the children terms of.
  * @param array  $terms The term data.
  *
  * @return array Returns nested child terms.
  */
function get_child_terms( $parent_id, $terms, &$order_terms = null ) {
  $children = array();
  foreach ( $terms as $term ) {
    if ( $term->parent == $parent_id ) {
      if ( $order_terms ) {
        array_push($order_terms, $term );
        get_child_terms( $term->term_id, $terms, $order_terms );
      } else {
        $children[ $term->term_id ] = $term;
        $children[ $term->term_id ]->children = get_child_terms( $term->term_id, $terms );
      }
    }
  }
  return $children;
}

第18行的$return_flat設定輸出為單層Array或者維持階層,設定為false的話子項目會存在children這個key裡。

測試看看。

$object_id = get_the_ID();
$taxonomies = 'category'; // here we use the default
$args = array( 'fields' => 'all' ); // options arguments

$categories = wp_get_object_terms( $object_id, $taxonomies, $args );
$terms = implode( '、', array_map(function($item) { return $item->name; }, $categories ));
echo $terms; // 關東、東京、代官山、澀谷、神奈川、橫濱

關東終於拿下他該有的位置了,很好!我們搞定。

解釋一下

事實上在後台設定了分類間的階層關係,也只會在Wordpress資料庫中新增一個parent欄位描述某個分類的上層id,所以資料本身是沒有分層的,我們必須再自己重新配對好它們的從屬關係才行。

事實上,Wordpress自己則是用了一個叫Walker類的方法,也一樣可以取得正確的階層分布,其基本原理也是會去「走」遍所有分類去做認親。

$object_id = get_the_ID();
$categories = get_the_category( $object_id );
$cat_ids = array_map( function($item) { return $item->term_id; },  $categories );
$args = array(
    'include' => $cat_ids,// 我們只取文章有使用到的分類 id 們
    'hierarchical' => true,
    'title_li' => '',   // 移除第一個大項目寫「分類」
    'style' => '',      // 設定成 list 以外的字串以避免輸出 ul>li
    'separator' => '、' // 將預設的 <br /> 改為中文頓號 
);
$terms = wp_list_categories( $args );
echo $terms; // 代官山、東京、橫濱、澀谷、神奈川、關東

成功!那你說我用wp_list_categories就好啦?不行。

假如今天沒有選用任何最上層分類的話,這裡就會出現bug。我們考慮同樣的分類階層,例如有一篇文章沒有勾選「關東」,只選用了其中的

  • 神奈川
    • 橫濱

這時候用Wordpress的內建函式wp_list_categories會得到

echo $terms; // 橫濱、神奈川

那欸阿餒?改用get_object_terms_hierarchical看看。

echo $terms; // 神奈川、橫濱

成功啦!

參考資料

  1. EricBusch/get_object_terms_hierarchical
  2. WordPress/get_the_category
  3. WordPress/wp_get_object_terms
  4. WordPress/wp_list_categories

在MacOS上啟用vhost虛擬主機

我們可以在Mac上使用預載好的Apache伺服器,就可以在瀏覽器網址輸入localhost來使用。除此之外,也可以透過設定打開個人資料夾,就可以把開發完成的網站都丟進去做測試。不過個人認為彈性更大、且簡潔的作法是直接設定vhost虛擬主機,透過和hosts搭配,就可以在本機端上部署多個任意網域。

例如:

  • dev.apple
  • dev.banana
  • dev.chocolate

欸,都是吃的是有多餓!不過這樣就可以為專案分門別類惹⋯⋯望向那凌亂的桌面,現實世界跟虛擬世界都一樣亂⋯⋯正文開始。

打開虛擬主機

首先要修改設定檔,進入終端機Terminal輸入:

sudo vi /etc/apache2/httpd.conf

在大約行數#517的位置,將下列行取消註解(把#字號刪掉)

#Include /private/etc/apache2/extra/httpd-vhosts.conf

這樣以來伺服器就會引入httpd-vhosts.conf這個設定檔,以設定不同網域分別對應的根目錄路徑。

設定網域根目錄

接下來就要修改vhost的設定,打開設定檔

sudo vi /etc/apache2/extra/httpd-vhosts.conf

例如我們把想資料夾/Users/aName/foo指派為dev.com對應的根目錄的話,就可以在內文插入

<VirtualHost *:80>
    DocumentRoot "/Users/aName/foo"
    ServerName dev.com
    ServerAlias www.dev.com
</VirtualHost>

設定網域指向

我們把網域對應到根目錄之後還要設定hosts,才能讓瀏覽器在本機端找到網域對應的實體ip位址,以現在的例子就是要把dev.com指到127.0.0.1,就是localhost的IP。首先打開hosts檔案

sudo vi /etc/hosts

加入這一行

127.0.0.1 dev.com

設定完成後,重啓伺服器就搞定。

sudo apachectl restart

權限處理

第一種:看不到網頁

如果在瀏覽器網址欄輸入dev.com遇到錯誤顯示

Forbidden
You don't have permission to access / on this server.

回到vhost設定檔,在設定dev.com的區塊</VirtualHost>標籤之前加入以下設定

<Directory "/Users/aName/foo">
    Options FollowSymLinks Multiviews Indexes
    MultiviewsMatch Any
    AllowOverride All
    Require all granted
</Directory>

再重新啟動伺服器,就好。

第二種:網頁程式沒有寫入權限

如果是看到

Forbidden
You don't have permission to access /folder/ on this server.
Server unable to read htaccess file, denying access to be safe

或是這類網頁檔案沒有權限寫入資料夾的狀況

The deployment path above must be writable by PHP in order to extract the archive file.

這裡會出現許多種作法,當然我們是可以利用chown -R修改資料夾及其內所有檔案權限為_www:_www,但是發現這樣在每次修改檔案的時候都要輸入密碼,因為此時檔案的擁有者不是自己,會變成類似在修改電腦系統檔案那樣很麻煩,所以我選擇把網頁的使用者跟群組乾脆改成自己,比較一勞永逸。

回到vhost設定檔,在設定dev.com的區塊<VirtualHost>標籤之外的地方加入以下設定

<IfModule unixd_module>
    User username
    Group staff
</IfModule>

其中,username請換成個人的使用者帳號名稱。然後再重新啟動伺服器,就好。

參考資料

  1. 在MacOS上使用Apache+PHP+MySQL
  2. 如何開啟個人資料夾

後記

雖然之前已經設定過了,但OS更新似乎會把原有的設定給覆蓋掉,結果又要重新設定一次⋯⋯覺得很麻煩於是做個記錄。

還有遇到問題再補(揍飛

3D Exhibition

Concept

Inspired from Codrops – Experimental 3D Room Exhibition Layout, but added further more functions! Now you can click every single image to get closer to it, and also available to read description and story behind photos.

Design

Origin post from Codrops is use 3D room as background only, but today I make it more joyful to play around. By separating the .content into .content-top and .content-bottom, we are now able to click on images behind scene! Then, I reuse the .info element with dynamically loading HTML content, so every picture can get its own information written side by side.

Also, I simplify navigation arrows animation to make it less distraction from focusing at gallery, modify color transition to menu icons so get more natural behavior, and add left/right arrow keyboard navigation supported.

On mobile phone, you can even tilt the device to change viewing perspective of room to get more closer to photo you are interested.

Playground

ひより/Hiyori/日和

前言

台灣人出國旅遊最熱門的國家,就是日本。無論在任何季節,都有著許多特色景點的國家,春天賞櫻、夏天新綠、秋天紅葉、以及冬天白雪。櫻花的粉紅,象徵一個旅遊部落格的開始,以此開始逐漸成長茁壯,與一般遊記式的景點介紹不同,著重在更多資訊的分享,以景點的特色風情為主、以個人的旅遊經驗為輔,並且透過精心拍攝及挑選的照片,希望傳遞給讀者最真實的感動。

簡介

偶爾會有的食記,除了名店以外也會介紹特色的小店,每一篇文章底下的資訊欄,都可以幫助讀者更快速的找到所需要的相關情報,讓人無須迷失在其他類似的遊記中。

首頁的三篇焦點文章,是作者為自己最近生活的最佳註解,亦提供最合時宜的當季精選。有需要的人則可以立即透過首頁的行動按鈕,傳送信息聯絡作者,洽詢相關的合作機會。

Hiyori在日文裡是晴天的意思,希望每一趟旅程,都成為美好的回憶、心情也放晴:)

SNW 2018

The 2018 Silicon Nanoelectronics Workshop is a satellite workshop of the 2018 VLSI Symposia sponsored by the IEEE Electron Device Society. It will be held on June 17-18, 2018 at the Hilton Hawaiian Village in Honolulu, Hawaii USA. This will be the 24th workshop in the annual series. Original papers on nanometer-scale devices and technologies that utilize silicon or which are based on novel materials on silicon substrates are welcome.

Go to site

Kotoba 和和字典

設計

後端基於CI的框架實作了一個日語字典網站,前端則運用MUI CSS實現Material Design的風格。註冊只需要使用者名稱,登入後可以把單字加入最愛,並且可以根據需求自行分類。歡迎大家進來玩玩~用手機的話還可以利用iOS的「加入主畫面」功能、或Android的「新增至主螢幕」功能,將網站設為常用桌面捷徑。

資料來源: weblio辞書

Go to page

待更新項目

  • 其他語言支援:英語、中文等
  • 更多個人化設定
  • PWA化

デザイン

バックエンドはCIに基づいてオンライン辞書を、フロントエンドはMUI CSSを基にしてMaterial Designを実装してみた。新規登録にUsernameだけ、登録したら、単語の管理や分類などをご自由に。よければ是非使ってみてください。携帯端末を利用する場合、iOSのSafari又はAndroidのChromeで「ホーム画面に追加」機能でショートカット作成することができる。