:::

Proxmox VE新增登入的方式

布丁布丁吃布丁

Proxmox VE新增登入的方式

image

Proxmox VE是一套開放原始碼的虛擬機器環境。儘管在虛擬機器的管理上提供了網頁介面的管理功能(Web GUI),可是在登入的連接埠、帳號與密碼卻無法直接設定。

本篇是以Proxmox VE 1.8來跟大家說明如何新增自己熟悉的登入方式,包括新增進入的連接埠而不只使用預設的443,以及建立的可登入的帳號與密碼而不是root。


新增帳號與密碼

Proxmox VE預設是使用「root」跟安裝時建立的密碼登入。如果你想要新增一個你自己習慣使用的帳號的話,可以新增一位使用者,使其群組編號為0,即root群組。這樣在網頁管理介面中,就能使用新增的帳號登入。具體來說,以下以新增帳號「pudding」為例,作法如下:

首先,先以root登入指令列端。然後使用useradd指令新增使用者,並搭配-g 0參數,將群組設為root。指令如下:

proxmox:~# useradd -g 0 pudding

接著是設定pudding的密碼,指令為passwd,系統會要你輸入兩次該帳號的密碼:

proxmox:~# passwd pudding
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
proxmox:~#

ok,這樣就完成了。

image

以pudding成功登入。

新增登入的連接埠

這邊使用的是iptables的連接埠轉遞功能,用來新增可以連入的連接埠,而不只有使用預設的443。

我習慣將iptables的指令寫在一個腳本檔中,然後再執行該腳本檔。確定沒問題之後,再到開機檔案/etc/rc.local當中。

首先,先新增一個檔案:/root/iptables.port-forward-webgui.rule。我習慣使用vim,指令如下:

proxmox:~# vim iptables.port-forward-webgui.rule

這邊要讓eth0網路卡的64443轉遞到443連接埠,並限定來源IP為192.168.11.0/24的範圍,而Proxmox VE的IP位置為192.168.11.13。請在root/iptables.port-forward-webgui.rule檔案中輸入以下內容:

iptables -t nat -A PREROUTING -i eth0 -p tcp -s 192.168.11.0/24 --dport 64443 -j DNAT --to-destination 192.168.11.13:443

然後改變該檔案的權限為771,使用chmod指令:

proxmox:~# chmod 771 /root/iptables.port-forward-webgui.rule

接著執行該腳本檔,看看是否能夠順利把64443轉到443連接埠去;

proxmox:~# /root/iptables.port-forward-webgui.rule

接著以HTTPS通訊協定與64443連接埠開啟Proxmox VE網頁管理介面看看。

image 

如上圖,注意網址中的連接埠,現在是以64443連到Proxmox VE的網頁管理介面囉。

確認沒問題之後,我們最後在開機時會執行的腳本檔 /etc/rc.local 最後一行加入執行該腳本檔的指令:/root/iptables.port-forward-webgui.rule

重開機看看,順利的話,那重開機之後依然可以以64443登入喔。重開機的指令為reboot:

proxmox:~# reboot 

不過就算經過這樣的設定,原本的443連接埠依然可以登入。用連接埠轉遞的方式似乎沒辦法只允許64443而不用443的樣子。


結語:資安與管理之間的取捨

上面介紹這些方法,並沒有取消原本預設的登入方式,而是新增其他的登入管道。站在資安的角度來看,等於是多增加一個讓人入侵的漏洞。不過這邊我是站在管理的角度來看,當你系統一多的時候,要背下各種不同的登入連接埠、使用者帳號名稱與密碼,這是很痛苦的一件事情。如果能把這些登入連接埠、帳號與密碼做個統一,那麼管理上會輕鬆許多。

當然,這也代表了一旦被人知道統一的登入連接埠、帳號與密碼的話,那整個組織的系統就完了。所以為了避免外部網路的駭客惡意入侵,在這邊有多做一個來源IP的限制,以防萬一。

如果你想要再更進一步提高Proxmox VE的資安防護,建議你參考我另一篇SSH資安防護建議,提高Proxmox VE的SSH資安防護能力吧。

(more...)

IPFire 修改預設登入方法

布丁布丁吃布丁

IPFire 修改預設登入方法

image

IPFire是一套小巧簡單易用的防火牆套件。他使用的是我們熟悉的CentOS,操作上也算是挺直覺得,也不會用常見的登入方式,以提高資安防護。預設登入方法很特殊,如果不記錄的話很容易就會忘記,這邊介紹IPFire 2.9版(安裝光碟ipfire-2.9.i586-full-core51.iso)如何自訂修改其登入的方法。


預設登入方法

預設登入的方法是在Green網卡 (內部區域網路)中透過HTTPS連線與444連接埠登入,而登入時會出現Apache認證,需要輸入帳號密碼才能進入IPFire管理畫面。

image

Apache認證需要輸入使用者名稱「admin」跟安裝IPFire時使用的密碼。

然而由於IPFire使用的登入方法比較特殊,我想要改成自己習慣的登入方式,所以打算進行以下修改:

  1. 增加另一個我自訂的連接埠
  2. 增加另一個登入的使用者名稱與密碼

以下詳細說明各個步驟。

增加自訂連接埠:透過Port Forwarding的方法

這方法比較簡單,但原本444連接埠依然可以連線,等於是另外多加一個自訂的連接埠。

image

進入上方導覽列的 firewall ,到side menu的port forwarding中,新增一個新的規則。規則如下:

  • Protocol: TCP
  • Alias IP: DEFAUL IP
  • Source port: 63443 (這個是你自訂的連接埠)
  • Destination IP: 你現在IPFire所在的IP
  • Destination port: 444
  • Remark: IPFire admin webpage (說明這個連接埠轉遞的用意)
  • Source IP, or network: 是否要限定範圍的IP才能連線,建議是設定,例如140.119.61.0/24僅供140.119.61.0~140.119.61.254連線,以提高資安保護

確定好之後就新增。

image

然後設定External Access,開放444連接埠供外部連線(也就是透過Red網卡連線)。

這樣就可以了。

有人會提出疑問,為何不修改Apache設定呢?這是因為Apache設定要調整的地方比較多,不熟悉的人做起來會很頭痛,所以在這邊並不推薦修改Apache設定。

增加使用者名稱與密碼

這邊開始要進入Linux指令列操作。

修改Apache設定檔

首先先修改Apache的設定檔。檔案位置是「/etc/httpd/conf/vhosts.d/ipfire-interface-ssl.conf」,將看到「Require user」開頭的地方最後都加入空白與你要使用的帳號,例如我要使用的是pudding,那麼就改成「Require user adminpudding」。

共有四處要修改,我這邊各別是:

  • 29行:Require user admin pudding
  • 38行:Require user adminpudding
  • 52行:Require user admin pudding
  • 61行:Require user dial adminpudding
新增Apache認證檔

然後再來新增Apache認證檔的使用者名稱與密碼。認證檔的位置在「/var/ipfire/auth/users」,設定認證檔的指令為「htpasswd」。如果要新增pudding帳號,則下以下指令:

[root@ipfire /]# htpasswd /var/ipfire/auth/users pudding

接著Linux會問你密碼,請輸入兩次相同密碼作為確認。

重新啟動Apache,完成

接著是重新啟動Apache,指令如下:

[root@ipfire /]# /etc/init.d/apache restart

或著你也可以重新啟動IPFire也無所謂。

image

這樣就可以用你剛剛設定的使用者名稱與密碼登入了。


結語

如何有效管理網路仍是每個網管致力不懈的難題。儘管IPFire特殊的方式提高了資安防護,但也讓一般人容易忘記怎麼連線。那麼還是要手動調整成符合當地文化的登入方式,這樣子就比較令人安心了。

(more...)

GLPI 強化知識庫目錄功能

布丁布丁吃布丁

0 Comments

GLPI 強化知識庫目錄功能

image

雖然GLPI提供了知識庫的功能,但是說實在的並不是很好操作。我修改了知識庫的目錄功能,讓他更容易使用。以下說明安裝方式跟強化的功能。這邊所說的是GLPI 0.80.2版本,安裝在Linux (CentOS)作業系統預設的Apache伺服器上,Windows作業系統的路徑並不一樣,請自行找尋位置。


安裝

※ [GLPI]請取代掉GLPI網頁目錄中的相對應位置。

Linux預設Apache的話,網頁檔案的位置在/var/www/html/glpi/。換句話說,完整路徑就是/var/www/html/glpi/inc/knowbaseitemcategory.class.php

功能

  • 知識庫的類別可以顯示備註的完整內容。
    image
  • 知識庫的類別具備直接編輯的連結。(開新視窗)
    image
  • 從類別路徑可以直接新增知識庫文章。
    image
  • 新增知識庫文章之後,跳到該類別的列表中,而不是回到知識庫首頁。 (2011/11/17)
  • 知識庫文章列表可以直接修改與跳到上傳檔案的位置。(2011/11/18)
    image

就這樣簡單的功能,可是卻能省下許多管理上的麻煩。

如果要新增子類別(子項)的話,可以到編輯類別的功能中操作。如下圖:

image

(more...)

在 PHP 使用 YUI Compressor 壓縮 JavaScript 跟 CSS

在 PHP 使用 YUI Compressor 壓縮 JavaScript 跟 CSS

2011-11-14_232832 yui logo

我在寫程式的時候,習慣搭配程式註解一併撰寫。寫JavaScript就搭配JSDoc,寫CSS就搭配CSSDoc,寫著寫著程式碼就會非常非常地龐大,造成使用者每次都要下載過大的檔案內容而效率緩慢。

YUI是一套開放原始碼的JavaScript與CSS框架,以BSD授權條款開放使用。它其中一個相當知名的功能是JavaScript與CSS的壓縮器(compressor)。這篇是要教你如何在PHP的環境中使用YUI Compressor來壓縮JavaScript與CSS。


安裝配置

由於這篇的目的是使用PHP作為開發環境,相信你已經有了一個運作PHP的環境。我自己的測試環境是以XAMPP 1.7.0架設,使用PHP 5.2.8。

首先,你要準備一個資料夾,用來擺放YUI Compressor與相關檔案。

再來將以下檔案下載到該資料夾中:

安裝Java

由於YUI Compressor使用Java,你必須確保你的環境中安裝了JDK才行。請到Java網站下載Java Platform (JDK),他有提供Windows與Linux各種版本。

然而我在CentOS作業系統中安裝JDK 7u1時不知為何地失敗了,所以我又回頭去裝了JDK 6u12。

下載之後,請調整該檔案的權限為755,然後執行該檔案。舉例來說指令如下:

[root@dspace ~]# chmod 755 jdk-6u12-linux-i586-rpm.bin
[root@dspace ~]# ./jdk-6u12-linux-i586-rpm.bin

如要確認Java能夠使用,請輸入以下指令並可能會看到如下訊息:(可能是因為我先裝7u1失敗的關係,以下版本顯示的是7u1而不是6u12)

[root@dspace ~]# java -version
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) Client VM (build 21.1-b02, mixed mode)

這樣就完成配置囉。


壓縮使用

使用YUI Compressor時,要先引用Minify_YUICompressor.php,然後透過它的靜態方法minifyJs()跟minifyCss()來輸入要壓縮的程式碼,並取得壓縮過後的程式碼。

以下是minifyJs跟minifyCss的用法:

/**
* Minify a Javascript string
*
* @param string $js
*
* @param array $options (verbose is ignored)
*
* @see http://www.julienlecomte.net/yuicompressor/README
*
* @return string
*/
public static function minifyJs($js, $options = array())

/**
* Minify a CSS string
*
* @param string $css
*
* @param array $options (verbose is ignored)
*
* @see http://www.julienlecomte.net/yuicompressor/README
*
* @return string
*/
public static function minifyCss($css, $options = array())

使用範例

為了讓大家更容易理解如何使用,請下載以下兩個範例檔案到上述Minify_YUICompressor.php跟yuicompressor-2.4.6.jar的同一個資料夾中。

我們先看一下blogger-template.css的原始碼,這是一個沒有經過壓縮的CSS程式,大概長得像下面這樣子,程式碼大小為19.9KB:

2011-11-14_232059 blogger-template.css

然後我們再透過minifyCss.php看一下壓縮過的樣子,壓縮過後程式碼大小為13.4KB,足足有67.3%的壓縮率:

2011-11-14_232133 minifyCss.php

以下是minifyCss.php的程式碼內容。這裡面包括了在HTTP標頭輸出為CSS格式的指令,以協助瀏覽器正確判斷資料內容。

<?php
header('Content-type: text/css', TRUE);

include("Minify_YUICompressor.php");
$script = file_get_contents("blogger-template.css");
$packed = Minify_YUICompressor::minifyCss($script);
echo $packed;

而JavaScript也是以此類推,以下是minifyJs.php壓縮JavaScript的標頭輸出與壓縮寫法:

<?php
header('Content-type: text/javascript', TRUE);

include("Minify_YUICompressor.php");
$script = file_get_contents("puliBloggerDigest.js");
$packed = Minify_YUICompressor::minifyJs($script);
echo $packed;


致謝與修改過程

YUI Compressor雖然一般是要透過Java以指令列的方式運作,不過多虧了minify專案開發了Minify_YUICompressor.php,讓我們得以輕易地以PHP使用YUI Compressor。

然而由於原本的Minify_YUICompressor.php需要將YUI Compressor跟暫存目錄指定為絕對路徑,我覺得不是很好用,所以將暫存目錄改為系統自訂的暫存目錄、YUI Compreesor改為跟Minify_YUICompressor.php相同的目錄,讓我們只要把兩個檔案擺在一起就能夠使用。這樣在程式碼轉移的時候特別方便,例如將PHP系統從Windows轉移到Linux的時候。

結語:最好搭配快取機制一起使用

YUI Compressor的壓縮功能雖然挺好用的,搭配上Minify程式之後就更容易讓PHP取用,但是運作效率卻有待堪慮。我在Windows環境中請YUI Compressor壓縮1MB左右的JavaScript的時候,通常會延遲個3秒鐘左右才完成。儘管這是因為我檔案太大的關係,但是如果太過頻繁的壓縮,恐怕仍會帶來效率上的問題。

我建議在使用YUI Compressor的時候,同時搭配一些快取機制(cache),將YUI Compressor的壓縮結果另存為一個靜態的JavaScript或CSS程式碼。下次就能讓系統直接讀取壓縮結果,而不需要經過YUI Compressor的壓縮。

(more...)

SSH資安防護建議

布丁布丁吃布丁

SSH資安防護建議

ssh

圖片來源:SSH tunnels for the common man (and woman)

SSH是Linux常用的通訊協定。儘管它是一種加密式的通訊協定,但是其實它很容易被用各種方法來取得進入的權限。為了提高SSH的安全性,我提出三層額外的SSH防護措施,以避免Linux直接暴露在網際網路的危險之中。


SSH簡介

SSH是Secure SHell protocol(安全的殼程式協定)的簡寫,他是一種封包加密技術,以確保封包在網路傳輸中不會因為中途竊取、監聽而暴露重要資料。SSH在Linux作業系統中已經被視為遠端操作用的基本工具,現在已經幾乎沒人在用telnet來操作Linux,除了BBS之外。詳細內容可以參考維基百科鳥哥的Linux私房菜的介紹。

然而,即使SSH已經是加密過的通訊協定,只要有心人士知道你的IP(用ping就可以抓到,或是各種方法都能知道你的伺服器IP)、連接埠(預設是22,或用連接埠掃描工具就知道)、帳號(預設是root)、密碼(透過暴力破解法猜測而得),那麼任何人依然可以輕易地登入你的主機、植入木馬、讓你的伺服器成為殭屍電腦

由於我們這邊常常有電腦遭駭客鎖定、攻擊,所以我思考了很多SSH防護的對策。以下介紹我目前的SSH三層防護措施:1. 防火牆設置白名單、2. 更改預設登入與連線方式、3. fail2ban。這三層的作法中,做完第一層就能達到一定程度的保護。如果不甚安心,或是無法限定白名單的話,那麼再進行第二層跟第三層的設定即可。


第一層:防火牆設置白名單

2011-11-14_171102 zentyal whitelist - mask

防火牆中的白名單(whitelist)是指較嚴謹的防護方式。只有白名單中IP範圍的電腦才能允許連線,否則全部都不能連線。

如果你所在網路中有架設防火牆統一管理,那麼可以請網路管理員幫忙設定。上圖是Zentyal防火牆套裝軟體的設定畫面,在這邊我將來源範圍設定為140.119.61.0/24,代表只有140.119.61.0~140.119.61.254這些IP範圍內的電腦才能連線,其他電腦都會被擋下來。

如果你沒有類似的防火牆伺服器,那麼也可以在Linux中使用iptables防火牆套件來配置。關於iptables請見我另一篇的說明,像是在iptables.allow的設定中加入以下設定:

iptables -A INPUT -i $EXTIF -s 140.119.61.0/255.255.255.0 -j ACCEPT #允許140.119.61.*的電腦連入

不過,當你不確定哪些電腦可以連入,譬如時常要從特定區域外面的網路中連回到Linux伺服器時,這種白名單就很難掌控。你有兩種作法可以作為應變:

  1. 準備一台白名單內的個人電腦,常常是公司內部的個人工作站,再透過該工作站連到Linux伺服器。
  2. 放棄使用白名單,僅做以下第二層與第三層的防護設定。

當然,我還是會建議你用第一種作法,而不是放棄白名單。

第二層:修改預設登入與連線方式

許多Linux安裝好之後,都會預設開放SSH(連接埠22),並允許root連線登入。所以駭客只要偵測到該IP開放22連接埠提供SSH服務,就可以用root帳號跟暴力破解法猜測密碼來登入。Ubuntu在這點做得不錯,它預設是關閉SSH,更不允許使用者用root直接登入。不過還是很多人打開了SSH連線,結果一樣很容易讓駭客進行暴力破解法猜測。

為了避免直接被猜測預設帳號與連線方式的方法,我提供以下幾個建議:

1. 新增另一個擁有root權限的帳號

為了避免直接被以root帳號猜測登入,我們要先準備另一個帳號,並給予他root般的權限,以方便進行伺服器管理。

Linux新增帳號的指令為useradd,然後再用passwd給予密碼。詳細操作請看鳥哥的帳號管理說明。舉例來說,我現在要以pudding作為另一個管理者帳號,作法如下:

[root@ipfire ~]# useradd pudding
[root@ipfire ~]# passwd pudding
Changing password for pudding
Enter the new password (minimum of 5, maximum of 127 characters)
Please use a combination of upper and lower case letters and numbers.
New password:
Re-enter new password:
Password changed.
[root@ipfire ~]#

接著修改帳號的uid,將之設為0,表示同等於root帳號。修改uid的位置在「/etc/passwd」檔案,打開該檔案之後,有一條設定將會是剛剛新增的帳號。舉例來說,剛剛新增的pudding帳號,其設定如下:

pudding:x:1001:1001::/home/pudding:

將這設定中的uid改成0,結果如下:(注意紅字的部份)

pudding:x:0:1001::/home/pudding:

關於「/etc/passwd」的詳細內容,請參考鳥哥的說明

2. 設定SSH,阻止root登入

SSH的設定檔預設位於「/etc/ssh/sshd_config」檔案中。

要阻止root帳號登入的話,則是在設定檔最後加上一條設定:(注意大小寫不同)

DenyUsers root

儲存之後,重新啟動SSH。之後SSH就不准給root登入了。

不使用PermitRootLogin no的理由

必須要說明的是,在此不使用大部分教學主張的「PermitRootLogin no」設定。這是因為該設定會一併擋掉前面建立的帳號,讓他無法登入。

如果是指令操作的話,還可以用su root換成root帳號。但是像是SFTP的操作就不能用su root切換,因此乾脆還是用擁有root權限的帳號比較方便。

3. 修改SSH連接埠

同樣是在「/etc/ssh/sshd_config」檔案中。

找到「Port 22」的設定,並將之改為其他的連接埠。舉例來說,如果要設定為透過64022來連接SSH的話,那就是改為「Port 64022」。

image

儲存之後,重新啟動SSH。之後SSH必須透過64022登入了。

弱點仍是暴力破解法

很遺憾的是,第二層作法只能防君子不能防小人。駭客依然可以透過掃描工具掃描伺服器連接埠,找到你修改後的SSH連接埠號碼,然後透過暴力破解法,猜測你的帳號與密碼組合。

具體來說,SSH雖然預設限制每次連線都只能嘗試登入5次,但是只要撰寫程式機器人,就可以不斷重複進行SSH並嘗試猜測帳號與密碼。這種程式並不難寫,可是卻很難防禦。為了阻止暴力破解法,你還需要第三層的防護:fail2ban。

第三層:fail2ban 限制登入失敗次數

fail2ban是Linux的一個套件,它會根據記錄檔來判斷使用者登入失敗的次數,來決定是否要阻止該使用者再次嘗試登入。舉例來說,你可以設定嘗試登入次數最高3次,超過次數之後必須等待1小時才能再登入。這樣駭客就很難用暴力破解法猜測你的密碼,因為他用錯誤的方式猜測,一天最多也能猜測24*3=72組帳號密碼而已。

關於fail2ban的安裝與設定方式,請參考我另一篇教學


結語

之前我這邊發生一件事情。我們同事平常用他工作用電腦連上Linux伺服器操作,然而他工作用電腦因為沒有定時更新防毒軟體,導致駭客入侵、成為殭屍電腦,一併感染了Linux伺服器。在這個案例中,第一層防護因為同事電腦位於白名單內而沒有效用,第二層與第三層防護,也因為同事電腦的帳號密碼直接被側錄,而跟著毫無效用。

同事的電腦不更新防毒軟體(實際上是已經過期了,卻又不更新授權),連帶導致的問題,讓計畫團隊足足有半個月沒有任何進度,而是在重灌伺服器跟修補漏洞。

這件事情告訴我們,任何角落都可能成為資安的漏洞來源,怎樣都擋不完。

不過,實際上也不要這麼悲觀。平時定期更新防毒軟體(免費的防毒軟體例如小紅傘Avira AntiVir PersonalAVG Anti-Virus FREE都不錯用)、架設伺服器時設定一下SSH的連線,將資訊安全當成常識一樣看待,將可以大幅降低駭客入侵的可能性。

(more...)

GLPI新增文件類型

布丁布丁吃布丁

GLPI新增文件類型

image

GLPI中上傳檔案時,會受到GLPI的文件類型管理限制。如果是未設定過的特殊文件類型,那上傳會失敗。這篇是講如何在GLPI 0.80.2中新增文件類型的方法。


1. 進入文件類型頁面

image

位置在「主頁 >設定 > 下拉列表」中,選擇「管理 文件類型」,再按下搜尋,就會進入文件類型的設定頁面。

2. 新增文件類型

image

新增文件類型的按鈕是上面導覽列的「+」。非常難發現,這是我覺得GLPI難以使用的缺點之一,雖然習慣就好。

image

接著進入「文件類型-建立」頁面。你可以輸入以下資料:

  • 名稱
  • 圖標(圖示)
  • 授權下載
  • 擴展名(副檔名的意思)
  • MIMIE類型
  • 備註說明

確定之後,按下「新增」按鈕就完成新增文件類型的動作。之後就可以用你設定的文件類型來上傳檔案了。


如果你使用GLPI的問題是檔案大小過大(預設是2MB),那必須調整php.ini的環境設定才行。關於放寬檔案大小設定的方法,請看我另一篇的說明。

(more...)

用JSON加快JavaScript的搜尋速度

用JSON加快JavaScript的搜尋速度

image

(圖片來源:ICON FINDER)

最近在寫JavaScript程式,在這邊跟大家分享一些程式撰寫的小技巧。JavaScript在網頁應用中通常是作為客戶端的應用程式,而JavaScript的運作速度時常取決於客戶端使用的瀏覽器與電腦效能。要執行複雜的JavaScript運算時,使用Google Chrome跟使用Internet Explorer (簡稱IE,特別是6以下)會有相當驚人的差距。

最近發現我的程式在IE上的瓶頸卡在「搜尋速度」上。如果修過資料結構的同學一定知道,資料結構最常探討的問題就是「搜尋」。提高搜尋速度有很多已知的方法,平常撰寫時通常只會實作最簡單但也是最沒效率的循序演算法(sequential search),而這也就是執行效率的瓶頸。然而多虧JavaScript的特殊資料結構JSON,我們也可以犧牲一些記憶體空間來換取非常快的執行速度,實作雜湊搜尋法(Hash Search)

以下就簡單介紹一下這些方法的差別。


低效率搜尋:循序演算法

現在我想要做一個函式(function),它會要求輸入一個字,並確認這個字是否是大寫英文,輸出「true」或「false」。

陣列版本

簡單一點的作法,我們可以用陣列(array)來實作:

/**
* 檢查一個字是否是英文大寫。(陣列搜尋版本)
* @param String _word 要檢查的字
* @return boolean 是英文,或不是英文
*/
function is_english_by_array(_word) {
var _english_list = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];

for (var _i in _english_list)
{
if (_word == _english_list[_i])
return true;
}
return false;
}

alert(is_english_by_array('Z'));

這是很直覺的寫法,要比對的資料組成一個陣列資料集,然後再一一比對。雖然看起來有點冗長,效率也不高。

正規表示法版本

聰明一點的人會用正規表示法(Regular Expression)來作字串的搜尋,以下是改用正規表示法的寫法:

/**
* 檢查一個字是否是英文大寫。(正規表示法版本)
* @param String _word 要檢查的字
* @return boolean 是英文,或不是英文
*/
function is_english_by_reg(_word) {
var _reg = /^([A-Z])$/;
return _reg.test(_word);
}

alert(is_english_by_reg('Z'));

看起來簡潔多了。但其實正規表示法的效率極差,這樣子的搜尋速度並不會快到哪裡去。

JSON與雜湊演算法

自從學會使用JSON之後,我就愛上了這種特殊的資料格式,特別是用在雜湊演算法的時候實在是很方便。

JSON介紹

以下引用維基百科對JSON的介紹

JSON(Javascript Object Notation)是一種輕量級的資料交換語言,以文字為基礎,且易於讓人閱讀。

JSON用於描述數據結構,有以下形式存在。

  • 物件 (object):一個物件以「{」開始,並以「}」結束。一個物件包含一系列非排序的名稱/值對,每個名稱/值對之間使用「,」分割。
  • 名稱/值對(collection):名稱和值之間使用「:」隔開,一般的形式是:
{name:value}

一個名稱是一個字串; 一個值可以是一個字串,一個數值,一個物件,一個布林值,一個有序列表,或者一個null值。

  • 值的有序列表(Array):一個或者多個值用「,」分割後,使用「[」,「]」括起來就形成了這樣的列表,形如:
[collection, collection]

  • 字串:以""括起來的一串字元。
  • 數值:一系列0-9的數位組合,可以為負數或者小數。還可以用「e」或者「E」表示為指數形式。
  • 布林值:表示為 true 或者 false。
雜湊搜尋法

用JSON實作雜湊搜尋法的方式,跟上面用陣列來實作的方式有點像:他們一樣是要準備一個可供搜尋的資料集,只是資料結構的方式完全不同。

以下是用JSON實作的雜湊搜尋法:

/**
* 檢查一個字是否是英文大寫。(JSON版本)
* @param String _word 要檢查的字
* @return boolean 是英文,或不是英文
*/
function is_english_by_json(_word) {
var _english_list = {'A':1,'B':1,'C':1,'D':1,'E':1,'F':1,'G':1,'H':1,'I':1,'J':1,'K':1,'L':1,'M':1,'N':1,'O':1,'P':1,'Q':1,'R':1,'S':1,'T':1,'U':1,'V':1,'W':1,'X':1,'Y':1,'Z':1};
return (typeof(_english_list[_word])=="number");
}

alert(is_english_by_json('Z'));

跟陣列把要比對的資料放在「值」(value)的方式不同,雜湊法中要比對的資料是放在「名稱」(name)當中。因此一旦用typeof()確認資料集中是否有該名稱時,就能夠知道搜尋的結果。

至於資料集中的值為何是用1?其實在此問題中用什麼值是無所謂,因為我只要確認該_word是否在待比對資料集裡面就好了。


結語

寫JavaScript實在是很有趣。

傳統在教資料結構時,大多是用C或Java在做教學。然而由於語言先天上的限制,像是強型別(Strong Type)、僅有基本的資料型態等等的特性,在實作資料結構與演算法時,其實是需要非常多步驟。對於JavaScript來說,既有JSON這個萬用的資料結構,也可以把function當做是資料型態,因此寫起程式來可說是非常靈活。

然而不僅僅只是在客戶端的應用,現在也越來越多人把JavaScript拿到伺服器端來使用,稱之為Server-side JavaScript (SSJS),目前相當知名應用之一就是Node.js

相信未來JavaScript會更加蓬勃發展,大家一起加油吧。

(more...)