大家都知道安全性是重要的,但是產業中的趨勢是直到最後一刻才加入安全性。既然不可能完全保護 Web 應用程序,那麼為什麼要費這個勁兒呢,不是嗎?不對。只要採用一些簡單的步驟就能夠大幅提升 PHP Web 應用程式的安全性。 開始之前 在本教學中,您將學習如何在自己的 PHP Web 應用程式中加入安全性。本教學假設您至少有一年編寫 PHP Web 應用程式的經驗,所以這裡不涉及 PHP 語言的基本知識(約定或語法)。目標是讓您了解應該如何保護自己建立的 Web 應用程式。 目標 本教學說明如何防禦最常見的安全威脅:SQL 注入、操縱 GET 和 POST 變數、緩衝區溢位攻擊、跨站點腳本攻擊、瀏覽器內的資料操弄和遠端表單提交。 前提條件 本教學是為至少有一年程式設計經驗的 PHP 開發人員所寫的。您應該了解 PHP 的語法和約定;這裡不解釋這些內容。有使用其他語言(例如 Ruby、Python 和 Perl)的經驗的開發人員也能夠從本教程中受益,因為這裡討論的許多規則也適用於其他語言和環境。 系統需求 需要一個正在運作 PHP V4 或 V5 和 MySQL 的環境。可使用 Linux、OS X 或 Microsoft Windows。如果是在 Windows 上,那麼下載 WAMPServer 二進位文件,並在機器上安裝 Apache、MySQL 和 PHP。 安全性快速簡介 Web 應用程式最重要的部分是什麼?根據回答問題的人不同,這個問題的答案可能是五花八門。業務人員需要可靠性和可擴展性。 IT 支援團隊需要健全的可維護的程式碼。最終用戶需要漂亮的使用者介面和執行任務時的高效能。但是,如果回答 “安全性”,那麼每個人都會同意這對 Web 應用程式很重要。 但是,大多數討論到此就打住了。儘管安全性在專案的檢查表中,但是往往到了專案交付之前才開始考慮解決安全性問題。採用這種方式的 Web 應用程式專案的數量多得驚人。開發人員工作幾個月,只在最後才添加安全特性,從而讓 Web 應用程式向公眾開放。 結果往往是一片混亂,甚至需要返工,因為程式碼已經經過檢驗、單元測試並集成為更大的框架,之後才在其中添加安全特性。添加安全性之後,主要組件可能會停止工作。安全性的整合使得原本順暢(但不安全)的過程增加額外負擔或步驟。 本教學提供一種將安全性整合到 PHP Web 應用程式中的好方法。它討論幾個一般性安全主題,然後深入討論主要的安全漏洞以及如何堵住它們。在學完本教學之後,您會對安全性有更好的理解。 主題包括: SQL 注入攻擊 操縱 GET 字串 緩衝區溢位攻擊 跨網站腳本攻擊(XSS) 提交 Web 安全性 101 在討論實現安全性的細節之前,最好從比較高的角度討論 Web 應用程式安全性。本節介紹安全哲學的一些基本信條,無論正在創建何種 Web 應用程序,都應該牢記這些信條。這些想法的一部分來自 Chris Shiflett(他關於 PHP 安全性的書是無價的寶庫),有些來自 Simson Garfinkel(參見 參考資料),還有一些來自多年累積的知識。 規則 1:絕對不要信任外部資料或輸入 關於 Web 應用程式安全性,必須認識到的第一件事是不應該信任外部資料。外部資料(outside data) 包含任何不是由程式設計師在 PHP 程式碼中直接輸入的資料。在採取措施確保安全之前,任何其他來源(例如 GET 變數、表單 POST、資料庫、個人資料、會話變數或 cookie)的資料都是不可信任的。 例如,下面的資料元素可以被認為是安全的,因為它們是在 PHP 中設定的。 清單 1. 安全無瑕的程式碼 $myUsername = 'tmyer'; $arrayUsers = array('tmyer', 'tom','tommy'); 🎜> define("GREETING", 'hello there' . $myUsername); ?> 但是,下面的資料元素都是有瑕疵的。 清單 2. 不安全、有瑕疵的程式碼 $myUsername = $_POST['username']; //tainted! $arrayUsers = array($myUsername, ' ', 'tommy'); //tainted! define("GREETING", 'hello there' . $myUsername); //tainted! ?> 為什麼第一個變數 $myUsername 瑕疵的?因為它直接來自表單 POST。使用者可以在這個輸入域中輸入任何字串,包括用來清除檔案或運行以前上傳的檔案的惡意命令。您可能會問,「難道不能使用只接受字母 A-Z 的客戶端(JavaScript)表單檢驗腳本來避免這種危險嗎?」是的,這總是一個有好處的步驟,但是正如在後面會看到的,任何人都可以將任何表單下載到自己的機器上,修改它,然後重新提交他們需要的任何內容。 解決方案很簡單:必須對 $_POST['username'] 執行清理程式碼。如果不這麼做,那麼在使用 $myUsername 的任何其他時候(例如在陣列或常數中),就可能污染這些物件。 對使用者輸入進行清理的一個簡單方法是,使用正規表示式來處理它。在這個範例中,只希望接受字母。將字串限制為特定數量的字符,或要求所有字母都是小寫的,這可能也是個好主意。 清單 3. 使用戶輸入變得安全 $myUsername = cleanInput($_POST['username']); //clean! $arrayUsers= array($myname,User 'tom', 'tommy'); //clean! define("GREETING", 'hello there' . $myUsername); //clean! function cleanInput($input){ = strtolower($input); $clean = preg_replace("/[^a-z]/", "", $clean); $cle return $clean; } ?> 規則 2:停用那些讓安全性難以實施的 PHP 設定 已經知道了不能信任使用者輸入,也應該知道不應該信任機器上設定 PHP的方式。例如,請確保停用 register_globals。如果啟用了 register_globals,就可能做一些粗心的事情,例如使用 $variable 來取代同名的 GET 或 POST 字串。透過停用這個設置,PHP 強迫您在正確的名稱空間中引用正確的變數。要使用來自表單 POST 的變量,則應引用 $_POST['variable']。這樣就不會將這個特定變數誤會成 cookie、會話或 GET 變數。 要檢查的第二個設定是錯誤報告等級。在開發期間,希望獲得盡可能多的錯誤報告,但是在交付專案時,希望將錯誤記錄到日誌檔案中,而不是顯示在螢幕上。為什麼呢?因為惡意的駭客會使用錯誤報告資訊(例如 SQL 錯誤)來猜測應用程式正在做什麼。這種偵察可以幫助駭客突破應用程式。為了封鎖這個漏洞,需要編輯 php.ini 文件,為 error_log 條目提供適當的目的地,並將 display_errors 設定為 Off。 規則 3:如果不能理解它,就不能保護它 一些開發人員使用奇怪的語法,或者將語句組織得很緊湊,形成簡短但是含義模糊的代碼。這種方式可能效率高,但是如果您不理解程式碼正在做什麼,那麼就無法決定如何保護它。 例如,您喜歡下面兩段程式碼中的哪一段? 清單 4. 讓程式碼容易受到保護 //obfuscated code $input = (isset($_POST['username']) ? ''); //unobfuscated code $input = ''; if (isset($_POST['username'])){ $input = 5_POST' ; }else{ $input = ''; } ?> 第二個比較清楚的程式碼片段中,很容易看出 $input 是有瑕疵的,需要進行清理,然後才能安全地處理。 規則 4:「縱深防禦」 是新的法寶 本教學將用範例來說明如何保護線上表單,同時在處理表單的 PHP 程式碼中採用必要的措施。同樣,即使使用 PHP regex 來確保 GET 變數完全是數位的,仍可採取措施確保 SQL 查詢使用轉義的使用者輸入。 縱深防禦不只是一種好思想,它可以確保您不會陷入嚴重的麻煩。 既然已經討論了基本規則,現在就來研究第一種威脅:SQL 注入攻擊。 防止 SQL 注入攻擊 在 SQL 注入攻擊 中,使用者透過操縱表單或 GET 查詢字串,將資訊加入資料庫查詢。例如,假設有一個簡單的登入資料庫。這個資料庫中的每個記錄都有一個使用者名字段和一個密碼欄位。建立一個登入表單,讓使用者能夠登入。 清單 5. 簡單的登入表單
Login
這個表單接受使用者輸入的使用者名稱和密碼,並將使用者輸入提交給名為 verify.php 的檔案。在這個文件中,PHP 處理來自登入表單的數據,如下所示: 清單 6. 不安全的 PHP 表單處理代碼 $okay = 0; $username = $_POST['user']; $pw = $_POST['pw']; $sql = "select count(*) as ctr from users whereusername='".$username='". password='". $pw."' limit 1"; $result = mysql_query($sql); while ($data = mysql_fetch_object($result)){ ctr == 1){ //they're okay to enter the application! y){ $_SESSION ['loginokay'] = true; header("index.php"); }else{ header("login.php"); } > 這段程式碼看起來沒問題,對嗎?世界各地數百(甚至成千)的 PHP/MySQL 站點都在使用這樣的程式碼。它錯在哪裡?好,記住 「不能信任使用者輸入」。這裡沒有對來自用戶的任何資訊進行轉義,因此使應用程式容易受到攻擊。具體來說,可能會出現任何類型的 SQL 注入攻擊。 例如,如果使用者輸入 foo 作為使用者名,輸入 ' or '1'='1 作為密碼,那麼實際上會將下列字串傳遞給 PHP,然後將查詢傳遞給 MySQL: $sql = "select count(*) as ctr from users where username='foo' and password='' or '1'='1' limit 1"; password='' or '1'='1' limit 1"; password='' or '1'='1' limit 1"; password是回傳計數值 1,因此 PHP 會允許存取。透過在密碼字串的末端注入某些惡意 SQL,駭客就能裝扮成合法的使用者。 解決這個問題的方法是,將 PHP 的內建 mysql_real_escape_string() 函數當作任何使用者輸入的包裝器。這個函數對字串中的字元進行轉義,使字串不可能傳遞撇號等特殊字元並讓 MySQL 根據特殊字元進行操作。清單 7 展示了帶有轉義處理的程式碼。 清單 7. 安全的 PHP 表單處理程式碼 $okay = 0; $username = $_POST['user']; $pw ='$pPO pw']; $sql = "select count(*) as ctr from users where username='".mysql_real_escape_string($username)."' and password='.". "; $result = mysql_query($sql); while ($data = mysql_fetch_object($result)){ if ($presult)){ 're okay to enter the application! $okay = 1; } header ("index.php"); }else{ header("login.php"); } ?> 使用 mysql_real_escape_string() 作為使用者輸入的包裝器,就輸入使用 mysql_real_escape_string() 作為使用者輸入的包裝器,就可以避免使用者輸入中的任何惡意 SQL 注入。如果使用者嘗試透過 SQL 注入傳遞畸形的密碼,那麼會將下列查詢傳遞給資料庫: select count(*) as ctr from users where username='foo' and password='' or '1'='1'1'='1 ' limit 1" 資料庫中沒有任何東西與這樣的密碼匹配。僅僅採用一個簡單的步驟,就堵住了 Web 應用程式中的一個大漏洞。這裡得出的經驗是,總是應該對 SQL查詢的使用者輸入進行轉義。使用者使用畸形的密碼進行登入。密碼,並不意味著他將按照規則行事 —— 他有很多機會能夠造成損害。 321 這樣的位置。用 $_GET['pid'] 存取這個字串。 pid = $_GET['pid']; //we create an object of a fictional class Page $obj = new Page; Page $obj = new Page; 🎜>//and now we have a bunch of PHP that displays the page ?> 這裡有什麼錯嗎?怎麼樣呢?如果他們輸入另一個數字,那麼可能沒問題;但是如果輸入別的東西,例如輸入 SQL 命令或某個文件的名稱(例如 /etc/passwd),或者搞別的惡作劇,例如輸入長達 3,000 個字符的數值,那麼會發生什麼事呢? 在這種情況下,要記住基本規則,不要信任使用者輸入。應用程式開發人員知道 template.php 接受的個人識別碼(PID)應該是數字,所以可以使用 PHP 的 is_numeric() 函數確保不接受非數字的 PID,如下: 清單 9. 使用 is_numeric( ) 來限制 GET 變數 $pid = $_GET['pid']; if (is_numeric($pid)){ $obj = new Page; $content = $obj->fetchPage($pid); }else{ //didn't pass the is_numeric() test, do something else! } ?> 這個方法似乎是有效的,但是以下這些都能夠輕鬆地通過以下這些輸入都能夠輕鬆地通過以下方式_ 檢查: 100 (有效) 100.1 (不應該有小數位) +0123.45e6 (科學計數法 - ) 那麼,有安全意識的 PHP 開發人員該怎麼做呢?多年的經驗表明,最好的做法是使用正規表示式來確保整個 GET 變數由數字組成,如下所示: 清單 10. 使用正規表示式限制 GET 變數 $ pid = $_GET['pid']; if (strlen($pid)){ if (!ereg("^[0-9]+$",$pid)){ /do something appropriate, like maybe logging them out or sending them back to home page } } //we create an object of a fictional class Page, which is now //moderately protected from evil pid ); //and now we have a bunch of PHP that displays the page ?> 需要做的只是使用 strlen(數字正規表示式來確保資料元素是有效的。如果 PID 包含字母、斜線、點號或任何與十六進位相似的內容,那麼這個例程捕捉它並將頁面從使用者活動中封鎖。如果看看 Page 類幕後的情況,就會看到有安全意識的 PHP 開發人員已經對使用者輸入 $pid 進行了轉義,從而保護了 fetchPage() 方法,如下所示: 清單 11. 對fetchPage() 方法進行轉義 class Page{ function fetchPage($pid){ des,$ppage where pid='".mysql_real_escape_string($pid)."'"; } } ?> 您可能會問,「既然已經確保數字轉義? 」 因為不知道在多少不同的上下文和情況中會使用 fetchPage() 方法。必須在呼叫這個方法的所有地方進行保護,而方法中的轉義體現了縱深防禦的意義。 如果使用者嘗試輸入非常長的數值,例如長達 1000 個字符,試圖發動緩衝區溢位攻擊,那麼會發生什麼事呢?下一節更詳細地討論這個問題,但是目前可以添加另一個檢查,確保輸入的 PID 具有正確的長度。您知道資料庫的 pid 欄位的最大長度是 5 位,所以可以加入下面的檢查。 清單 12. 使用正規表示式和長度檢定來限制 GET 變數 $pid = $_GET['pid']; if (strlen($pid)){ if (!ereg("^[0-9]+$",$pid) && strlen($pid) > 5){ them back to home page } } else { //empty $pid, so send them a fictional class Page, which is now //even more protected from evil user input $obj = new Page; ?> 現在,任何人都無法在資料庫應用程式中塞進一個 5,000 位的數值 - 至少在涉及 GET 字串的地方不會有這種情況。想像一下駭客在試圖突破您的應用程式而遭到挫折時咬牙切齒的樣子吧!而且因為關閉了錯誤報告,駭客更難進行偵察。 緩衝區溢位攻擊 緩衝區溢位攻擊 試圖使 PHP 應用程式中(或更精確地說,在 Apache 或底層作業系統中)的記憶體分配緩衝區發生溢位。請記住,您可能是使用 PHP 這樣的高階語言來編寫 Web 應用程序,但最終還是要呼叫 C(在 Apache 的情況下)。與大多數低階語言一樣,C 對於記憶體分配有嚴格的規則。 緩衝區溢位攻擊向緩衝區發送大量數據,使部分資料溢位到相鄰的記憶體緩衝區,從而破壞緩衝區或重寫邏輯。這樣就能夠造成拒絕服務、破壞資料或在遠端伺服器上執行惡意程式碼。 防止緩衝區溢位攻擊的惟一方法是檢查所有使用者輸入的長度。例如,如果有一個表單元素要求輸入使用者的名字,那麼在這個網域上新增值為 40 的 maxlength 屬性,並在後端使用 substr() 進行檢查。清單 13 給出表單和 PHP 程式碼的簡短範例。 清單 13. 檢查使用者輸入的長度 if ($_POST['submit'] == "go"){ $name = substr($_POSTsubstr($_Hname'name'name' ],0,40); } ?>
為何既提供 maxlength 屬性,又在後端進行substr() 檢查?因為縱深防禦總是好的。瀏覽器防止使用者輸入 PHP 或 MySQL 無法安全處理的超長字串(想像一下有人試圖輸入長達 1,000 個字元的名稱),而後端 PHP 檢查則確保沒有人遠端地或在瀏覽器中操縱表單資料。 如您所看到的,這種方式與前一節中使用 strlen() 檢查 GET 變數 pid 的長度相似。在這個範例中,忽略長度超過 5 位元的任何輸入值,但是也可以輕鬆地將值截斷到適當的長度,如下所示: 清單 14. 改變輸入的 GET 變數的長度 $pid = $_GET['pid']; if (strlen($pid)){ if (!ereg("^[0-9]+$",$pid )){ //if non numeric $pid, send them back to home page ¢ back to the home page } //we have a numeric pid, but it may be too long, so let's check } //we create an object of a fictional class Page, which > $obj = new Page; $content = $obj->fetchPage($pid); //and now we have a bunch of PHP that displays the page ?>
不注意,數字緩衝區溢位 ?> 字母串。也可能會看到長的十六進位字串(往往看起來像 xA3 或 xFF)。記住,任何緩衝區溢位攻擊的目的都是淹沒特定的緩衝區,並將惡意程式碼或指令放到下一個緩衝區中,從而破壞資料或執行惡意程式碼。對付十六進制緩衝區溢位最簡單的方法也是不允許輸入超過特定的長度。 如果您處理的是允許在資料庫中輸入較長條目的表單文字區,那麼無法在客戶端輕鬆地限制資料的長度。在資料到達 PHP 之後,可以使用正規表示式清除任何像十六進位的字串。 清單 15. 防止十六進位字串 if ($_POST['submit'] == "go"){ $name = substr($_POSTsubstr($_POST[' name'],0,40); //clean out any potential hexadecimal characters $name = cleanHex($name) ; function cleanHex($input){ $clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "",$input); return $clean; } ?>
您可能會發現這一系列操作有點太嚴格了。畢竟,十六進位串有合法的用途,例如輸出外語中的字元。如何部署十六進位 regex 由您自己決定。比較好的策略是,只有在一行中包含過多十六進位串時,或當字串的字元超過特定數量(例如 128 或 255)時,才刪除十六進位串。 跨站點腳本攻擊在跨站點腳本(XSS)攻擊中,往往有一個惡意用戶在表單中(或通過其他用戶輸入方式)輸入信息,這些輸入將惡意的客戶端標記插入過程或資料庫中。例如,假設網站上有一個簡單的來客登記簿程序,讓訪客留下姓名、電子郵件地址和簡短的訊息。惡意使用者可以利用這個機會插入簡短訊息之外的東西,例如對於其他使用者不合適的圖片或將使用者重定向到另一個網站的 JavaScript,或竊取 cookie 資訊。 幸運的是,PHP 提供了 strip_tags() 函數,這個函數可以清除任何包圍在 HTML 標記中的內容。 strip_tags() 函數也允許提供允許標記的列表,例如 或 。 清單 16 給出一個範例,這個範例是在前一個範例的基礎上建構的。 清單 16. 從使用者輸入清除 HTML 標記 if ($_POST['submit'] == "go"){ strip_tags($_POST['name']); $name = substr($name,0,40); //clean out any or>$hexadecimal> //continue processing.... } function cleanHex($input){ $clean = preg_replace("![F-9]( {1,3})!", "",$input); return $clean; } ?>
注意,隱藏變數之一暴露了表名:users。也會看到一個值為 create 的 action 欄位。只要有基本的 SQL 經驗,就能夠看出這些指令可能控制著中間件中的一個 SQL 引擎。想搞大破壞的人只要改變表名或提供另一個選項,例如 delete。 圖 1 說明了 Tamper Data 能夠提供的破壞範圍。請注意,Tamper Data 不但允許使用者存取表單資料元素,還允許存取 HTTP 頭和 cookie。 圖 1. Tamper Data 視窗 要防禦此工具,最簡單的方法是假設任何使用者都可能使用 Tamper Data(或類似的工具)。只提供系統處理表單所需的最少量的信息,並把表單提交給一些專用的邏輯。例如,註冊表單應該只提交給註冊邏輯。 如果已經建立了一個通用表單處理函數,有許多頁面都使用這個通用邏輯,那該怎麼辦?如果使用隱藏變數來控制流向,那該怎麼辦?例如,可能在隱藏表單變數中指定要寫哪個資料庫表或使用哪個檔案儲存庫。有 4 種選擇: 不改變任何東西,暗自祈禱系統上沒有任何惡意使用者。 重寫功能,使用更安全的專用表單處理函數,避免使用隱藏表單變數。 使用 md5() 或其他加密機制對隱藏表單變數中的表名或其他敏感資訊進行加密。在 PHP 端不要忘記對它們進行解密。 透過使用縮寫或暱稱讓數值的意義模糊,在 PHP 表單處理函數中再對這些數值進行轉換。例如,如果要引用 users 表,可以用 u 或任意字串(例如 u8y90x0jkL)來引用它。 後兩個選項並不完美,但是與讓使用者輕鬆猜出中間件邏輯或資料模型相比,它們要好得多了。 現在還剩下什麼問題呢?遠端表單提交。 遠端表單提交 Web 的好處是可以分享資訊和服務。壞處也是可以分享資訊和服務,因為有些人做事毫無顧忌。 以表單為例。任何人都能夠存取一個 Web 站點,並使用瀏覽器上的 File > Save As 建立表單的本機副本。然後,他可以修改 action 參數來指向一個完全限定的 URL(不指向 formHandler.php,而是指向 http://www.yoursite.com/formHandler.php,因為表單在這個網站上),做他希望的任何修改,點選 Submit,伺服器會把這個表單資料當作合法通訊流接收。 首先可能考慮檢查 $_SERVER['HTTP_REFERER'],從而判斷請求是否來自自己的伺服器,這種方法可以擋住大多數惡意用戶,但是擋不住最高明的駭客。這些人足夠聰明,能夠篡改頭部中的引用者信息,使表單的遠端副本看起來像是從您的伺服器提交的。 處理遠端表單提交更好的方式是,根據一個惟一的字串或時間戳產生一個令牌,並將這個令牌放在會話變數和表單中。提交表單之後,檢查兩個令牌是否符合。如果不匹配,就知道有人試圖從表單的遠端副本發送資料。 要建立隨機的令牌,可以使用 PHP 內建的 md5()、uniqid() 和 rand() 函數,如下: 清單 18. 防禦遠端表單提交 session_start(); if ($_POST['submit'] == "go"){ //check token ($_POST ']){ //strip_tags $name = strip_tags($_POST[name']); //clean out any potential hexadecimal characters $name = cleanHex($name); //stop all processing! remote form posting attempt! } } $token = md5(uniqid(rand(), true)); $_SESSION['token']= $token; function cleanHex($input){ $clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "",$input); return $clean; } ?>
這種技術是有效的,這是因為在 PHP 中會話資料無法在伺服器之間遷移。即使有人獲得了您的 PHP 原始程式碼,將它轉移到自己的伺服器上,並向您的伺服器提交訊息,您的伺服器接收的也只是空的或畸形的會話令牌和原來提供的表單令牌。它們不匹配,遠端表單提交就失敗了。 結論 本教學討論了許多問題: 使用 mysql_real_escape_string() 防止 SQL 注入問題。 使用正規表示式和 strlen() 來確保 GET 資料未被竄改。 使用正規表示式和 strlen() 來確保使用者提交的資料不會使記憶體緩衝區溢位。 使用 strip_tags() 和 htmlspecialchars() 防止使用者提交可能有害的 HTML 標記。 避免系統被 Tamper Data 這樣的工具突破。 使用惟一的令牌防止使用者遠端向伺服器提交表單。 本教學沒有涉及更進階的主題,例如檔案注入、HTTP 頭欺騙和其他漏洞。但是,您學到的知識可以幫助您馬上增加足夠的安全性,使當前專案更安全。 參考資料 學習 在 Zend.com 上尋找有用的 PHP 101 教學。 取得 Chris Shiflett 的 Essential PHP Security 的複製。他所做的介紹比本教程深入得多。 取得 Simson Garfinkel 的 Web Security, Privacy & Commerce 的副本。 進一步了解 PHP Security Consortium。 閱讀 「Top 7 PHP Security Blunders」。 查閱 developerWorks 「建議的 PHP 讀物清單」。 閱讀 developerWorks 文章 「審計 PHP,第 1 部分: 理解 register_globals」。 查看 PHP Security HOWTO 網路廣播。 造訪 IBM developerWorks 的 PHP 專案參考資料 進一步了解 PHP。 隨時關注 developerWorks 技術活動與網路廣播。 了解世界各地為 IBM 開放原始碼開發人員的即將舉行的會議、內部預覽、網路廣播和其他 活動。 存取 developerWorks 的 開放原始碼專區,這裡有豐富的 how-to 資訊、工具和專案更新,可協助您利用開放原始碼技術開發並用於 IBM 產品。 要想聽聽軟體開發人員之間有意思的訪談與討論,就一定要查閱 developerWorks podcasts。 取得產品與技術 Windows 使用者可以下載 WAMPServer。 用 PHP 建立您的下一個開發項目。 使用 IBM 試用軟體 改善您的下一個開放原始碼開發項目,這些軟體可以下載或透過 DVD 取得。 討論 透過參與 developerWorks blog 加入 developerWorks 社群。 關於作者 Thomas Myer 是 Triple Dog Dare Media 的創始人和主要人物,這是一家位於德州 Austin 的 Web 諮詢公司,專長諮詢於資訊系統結構、Web 應用程式開發和 XML 他是 No Nonsense XML Web Development with PHP(由 SitePoint 出版)的作者。