
日期:2006-09-21 作者:喜騰小二 來源:PHPChina
作者 Kevin Kardasz、Vadim Kudryavtsev、Robert
Mark、Mikhail Seliverstov
麥吉爾大學的開發與校友關係部如何使用 PHP 和 Oracle 在網上支援多達 16
萬名使用者
在麥吉爾大學(位於加拿大魁北克省的蒙特利爾)的開發與校友關係部,我們正在使用行業級的 PHP 應用程式和
Oracle9i,將範圍廣泛的多層次服務轉移到 Web 上,這些服務由 200 到 300 名受薪的和誌願的工作人員以及多達 16
萬名校友和捐贈人使用。預計該程式在主要的電子廣播時段每小時將會接納數萬名使用者。我們利用 Oracle 功能強大的行級安全特性以及 PHP
的高效能和快速開發平臺來完成這一工作。本文將探討以下方麵:
背景
我們的機構麵臨着很多機構所麵臨的問題:
我們已經啓動了安全的、基於 Web 的模組化資料庫應用程式開發的第一階段。它以 PHP 和
Oracle9i 編寫而成,在替代衛星應用程式及 Web
站點之後,必將為使用者提供更好的服務。它對公共資料進行同步,並在總體上以及資料方麵加強最佳業務慣例的應用。
該應用程式稱為
Companion,因為它增加了反嚮中央資料庫的功能,準確地報告中心資料,並在出現新資料時將其回送。
它包含超過 100 個表,這些表被分為 6 個模組。最長的表大約有一百萬行。有些表有 20 到 30
列。全部用途是由用於行級安全性的 Oracle 細粒度訪問控制 (FGAC) 和虛擬私用資料庫 (VPD) 構成的。
Companion 應用套裝程式含三個域,而且能夠容納更多的域,這些域全都安全地訪問同一 PHP/Oracle
應用程式中的相同資料。這些域包括以下內容:
Apache 和 Linux。二者都以強健、低成本和安全性(在正確配置的情況下)而着稱。除了作為資料庫伺服器操作係統給人留下深刻印象之外,我們還發現 Linux
的 Debian 版本(來自 http://www.debian.org/ 的 Debian 項目)特別適合作為 Web
伺服器,原因在於它在開放源程式碼社區中俱有非常高的支援率、其整合軟體的高質量以及它在穩定性方麵的良好聲譽。
PHP。我們沒有選擇 Active Server
Pages、ColdFusion 和 JSP,而是選擇 PHP 作為我們的 Web 伺服器端指令檔環境,原因在於它的速度、成本效益、大量的庫檔案以及比其他 Web
技術更好的自訂功能。使用 PHP 還使我們免於束縛在特定廠商的開發工俱集上。透過一個由 Web
網站以及程式設計人員論壇(提供關於如何處理進階故障的有用提示)組成的網路,可以在 Web 上獲得支援。有些 Web
網站還提供大量可用於開發更大型應用程式元件的有效程式碼。大部分程式設計人員很容易理解 PHP 程式碼,因為它使用了與 C 相似的語法。我們討論過,使用 Java
來開發我們所期望的伺服器物件,其執行效率高於指令檔程式碼。但是,我們尚未發現需要與 Java 整合,因為已經證明 PHP 非常靈活和快速,足以滿足我們的需要。清單 1 顯示了一個透過 PHP 查詢 Oracle 的範例。
在進行更加復雜的麵嚮物件的編程時,使用 PHP
的不足就會顯現出來。這是因為它最初是作為一種指令檔語言建置的,所以在 PHP 第 4 版中麵嚮物件的特性非常少。這一問題已在 PHP 第 5
版中得以解決,該版本中引入了進階的麵嚮物件特性。
Oracle9i。在不使用協力廠商工俱的情況下,保持 Companion 資料庫與中央資料庫的同步是我們的首要需求之一。在兩個
Oracle9i 係統之間交換資料將會證明比開發其他轉換和傳輸資料的方法要容易得多。在我們的案例中,使用 Oracle9i帶來的好處與我們的投入相比要大得多,這是因為我們能夠利用先前 PL/SQL 程式碼,從而節省了開發時間。由於 Oracle 也移植到了 Linux
上,因此我們現在在 PC 體係結構的資料庫伺服器操作係統方麵有了更多的選擇。雖然中央資料庫執行在 Oracle8i 上,但我們選擇使用
9i 進行開發,以利用其更加先進的 VPD 特性(如 FGAC 和安全應用程式環境),它是市場上俱有這些功能的唯一平臺。
Companion 應用程式的結構
如同許多軟體項目一樣,我們開發團隊的目的就是,基於可重用安全性元件和資料訪問元件的框架,建立由多個功能獨立的模組組成的靈活、可伸縮的應用程式。以下就是我們如何做到這一點的。
N 層體係結構。為了確保應用程式的可移植性和按需延伸的能力,需要對總的體係結構進行分層 —
換句話說,分為兩層或多層,從而減少在某些基礎性技術過時或者不能滿足我們的需要時重新編寫整個應用程式的風險。
在經過大量思考後,我們決定選用自訂的 n
層體係結構(該結構考慮了應用程式的需求以及機構的俱體情況),而沒有采用較傳統的兩層或三層的方法。(參見圖 1。)
![]() |
GUI 呈現層是最終使用者利用其本機浏覽器實際看到並處理的內容。該層包含由底層生成的 HTML 页面和表單,還包括用來強化外觀和導航的用戶端
Javascript 和 CSS(層疊樣式表)。該層的主要目的是收集使用者輸入和提供輸出。
呈現邏輯層位於伺服器上,隻包含那些按功能邏輯分類的 PHP
指令檔。它包含呈現範本和佈局、驗證常式以及特定模組私用的指令檔。該層主要用於驗證和處理使用者輸入,並基於從使用者和更低層次接收的資料準備輸出。
業務邏輯層是實施大部分業務規則的層次(由於安全原因,將某些關鍵規則嚴格限制在資料庫級,而沒有暴露給應用程式級)。它提供了 PHP
類的集合,這些 PHP
類封裝了係統各部分私用的規則。此外,該層包含安全框架。該框架透過提供使用者驗證、工作階段管理和請求授權等機制,在應用程式級上管理使用者的訪問。特別是,該框架提供了很多公共方法,允許較高的層次基於安全授權權對使用者介麵進行自訂。最後,該層包含可重用的通用類。應用程式使用這些類來進行資料加密、壓縮、資料類型轉換等。
資料抽象邏輯層由一組通用方法構成,用於為應用程式提供與存儲在資料庫中的實際資料的介麵。換句話說,它在資料層與係統的其餘部分之間提供了一個額外的抽象級別,這使應用程式真正獨立於資料庫引擎。在經過大量測試後,我們選擇了另一種開放源程式碼工俱
ADODB 庫 (http://php.weblogs.com/) 來提供這種功能。
資料層又稱 Oracle,無疑是該係統中最重要且最復雜的部分。其安全機制將在以下的安全章節中進行解釋。
在圖 2 中描述了
Companion 應用程式的實體佈局:
![]() |
模組。每個模組均由資料結構(表和視圖)和
PL/SQL 套裝程式的組成。結構與套裝程式都透過業務邏輯層中的 PHP 類與 GUI
應用程式相整合,以提供一係列主題統一的功能。模組化結構不僅使開發和組織功能的工作變得合乎邏輯且一緻,而且對安全性也是一樣。
模組在邏輯上是相互分離的。每個模組都擁有一套獨有的安全策略,在 Web 伺服器上擁有自己的裝滿其 PHP
應用程式檔案的檔案夾,並且擁有自己的 GUI
子站點和表集。每個表名以兩個表示該表所屬模組的字母作為首碼。檔案、策略、過程以及其他存儲的程式碼集均遵循一種命名慣例,這種慣例將它們標識為特定模組的一部分。
在某種意義上,模組是相互分離的,但每個模組都嵌入到更大的應用程式中。模組共用相同的導航元素和公用資料,並且全都重用業務邏輯層提供的類。
| 表 HR_Employee c1_id c1_emp_category web_emp_photo c2_emp_email ------- ---------------- -------------- ------------ M290171 central staff (blob) james.milton@mcgill.ca C179022 central staff (blob) doris.seagal@mcgill.ca M109022 casual (blob) luke.grande@mcgill.ca C390101 work-study (blob) patrick.roy@mcgill.ca M203400 faculty based staff (blob) mcmaster.philip@mcgill.ca 表和欄位的首碼碼: HR — 人力資源模組(每個模組的每個表都有兩個字母的首碼) C1 — 中央資料庫 1* C2 — 中央資料庫 2* WEB — Companion 資料庫應用程式* * 欄位的首碼依據其源資料庫確定。 由於該應用程式是 companion 資料庫, 它同步並使用來自於不同來源的資料, 尤其是來自於主要中央資料庫的資料。 |
雖然大部分模組遵守相似的安全結構和原則,但是在項目開始的時候,我們的每個模組都需要有專門針對其需求的安全方案。共同安全原則的一個例子是指導者原則。為每個模組大緻分配三位指導者。指導者通常是符合條件的非技術性使用者。他們在其模組內擁有完全的管理授權權,並可以嚮其他較低安全級的管理員分配授權權。不同安全原則的一個範例是 HR
模組中保密資訊原則。當員工訪問其保密資訊時,他們的行級安全依賴於其實體 ID。但是在大多數其他模組中,他們的行級安全依賴於其工作的職位 ID。
安全性
如果我們的資料非常敏感,則透過傳統的基於 cookie
的工作階段機制在應用程式級上限制訪問就不足以保證安全性。對於俱有復雜的訪問規則並且預期俱有龐大流量的資料庫而言,在管理行級安全的同時獲得良好效能的最佳方法是將大部分安全功能
— 那些用於強化資料限制的特定規則的安全功能 — 轉移到資料庫級。
透過 VPD
保護資料庫引擎級上的資料訪問的安全而將訪問控制放在了最低級別上,從而確保入侵者的查詢工俱(能夠越過應用程式安全機制)無法獲得資料。此外,它為機構提供了更低的擁有成本:在資料伺服器上一次性建置安全性,而不用將安全性建置到所有訪問資料的應用程式工俱中。最後,它集中了資料訪問的管理和控制。
Companion 利用了 Oracle
傳統的基本角色安全和使用者帳戶安全功能。更重要的是,它使用了兩個功能強大的 VPD 工俱:安全應用程式環境和 FGAC。(有關 VPD 的詳細幫助,參見 otn.oracle.com/deploy/security/oracle9ir2/pdf/VPD9ir2twp.pdf)。使用這四個安全性概念作為框架,讓我們來探討我們的業務模型如何與
Oracle 相融合。
基本使用者帳戶安全。安全性和資料庫體係結構是圍繞一個每天從中央資料庫進行更新的主要名稱清單而設計的。這些名稱被稱為實體而非使用者。
Companion 包含兩個使用者組,工作人員和畢業生。使用者組被 Oracle
的基本安全功能看作單個帳戶。舉例來說,這意味着 3
萬個併發使用者隻共用兩個帳戶。其他使用者(包括某些實體和所有的非實體)無法共用任何帳戶,但它們仍然可以訪問未加限制的公共資料。(注意:在本文中,使用者指訪問係統的人,而帳戶指 Oracle 基本使用者帳戶。)如圖 3 所示,使用者是公共實體和成員的子集。
![]() |
那麼為什麼僅為所有經過驗證的使用者分配兩個共用帳戶,而不是分別為每個使用者分配一個帳戶?因為對許多應用程式安全性的管理,需要依據使用者可能賦予這些應用程式的各種內容進行,而非依據使用者所擁有的帳戶進行。可完成此目的的工俱將在以下關於
VPD 的章節中進行探討。
基本角色安全。當使用者透過按一下某個連結訪問
Companion 應用程式時,從安全性的觀點來看,使用者是在訪問模組。每個模組都與一個 Oracle
安全形色相關聯,該角色被分配或被拒絕賦予每個使用者帳戶。這些安全形色管理表、視圖、過程和函式等的物件級安全。基本角色安全隻是將廣泛的使用者授權權(選擇、插入、執行等)分配給物件,它是建立訪問的第一步。特定的使用者授權權由
FGAC 控制。
VPD 安全應用程式環境。Companion
應用程式使用 Oracle 的安全應用程式環境,將實體 ID 分配給登入的使用者。利用兩個簡單的識別碼 — 帳戶(工作人員或畢業生)和環境(實體 ID)—
即可確立大部分的訪問規則,並且很容易派生出其餘的規則。
這些用於使用者登入工作階段的識別碼由一個加密的安全權杖所攜帶,每次進行查詢(即按資料庫中某項內容的超連結)時都會讀取該權杖。在加密權杖的工作階段持續期間,使用者登入(名稱/口令)以及實體
ID 都存儲在 Web 伺服器上。登入用於建立與資料庫的連線並獲得對資料結構的訪問授權權,而實體 ID
則用於透過安全策略將資料訪問授權權細化到在行級。
VPD 細粒度訪問控制。使用由安全應用程式環境提供的實體 ID 識別碼,Oracle 安全策略能夠在行級管理訪問。這些 FGAC 安全策略 —
與基本角色安全一樣 — 附加在物件上。與基本角色安全不同的是,FGAC 策略進一步將訪問授權權限制在與實體 ID
關聯的內容上。附加到所有非公共資料庫物件上的安全策略有助於完全剝離受限制的資料。因此,即使資料庫登入名和口令被盜取,對任何受策略保護的表進行查詢的企圖(使用標準
SQL
工俱)都將得到空記錄集或有限的記錄集。策略對使用者的內容以及行的內容進行鑒定,並確定使用者可以看到哪些行(如果有的話)。例如,隻有那些住在溫哥華並應邀出席西海岸地區經理宴會的實體才可以檢視出席同一活動的登記者名單。另一個例子:分配到
Web 站點的編輯人員不能移除網站的页面,但該網站的作者可以這樣做。
共性。我們的 160,000
個實體構成了一個變化的復雜群體。每個實體都有很多共性,如年齡、地位、財政群體、地區等等。為了便於沒有經驗的管理員分配訪問授權權,已經將許多這樣的內容彙總到一係列的共性組中。有一個共性查詢表每天都進行更新,並列出所有實體及其相應的共性。FGAC
也使用該表管理對那些已經分配了共性的資料行的訪問。共性還用於為站點的訪問者靈活地提供個性化的內容。
圖 4描述了在使用者調用页面時篩選資料請求的五個步驟。
![]() |
使存儲在 Companion
資料庫中的資料與存儲在中央資料庫中的資料保持同步已變成了一項挑戰,因為二者都在不斷地更新。我們設計了一個係統,它比即時係統慢,但是保證符合嚴格的資料標準。
起初,每夜在 Companion 資料庫中重新整理由中央資料庫提供的“同步”資料(參見圖
5)。這一傾印過程中最重要的物件是實體表,它構成了我們內部安全性的基礎。
雖然該組同步表在 Companion
應用程式的模組中被頻繁使用,但它們並不由這些模組進行更新。實際上,這些更新存放在保持表中,如果有必要,由記錄工作人員使用專門設計的客戶伺服器介麵對其進行仔細的編輯。然後,更新的資料在經過編輯從而符合標準之後,被回送到中央資料庫。由於中央資料庫和
Companion
資料庫中的所有行都有日期時間標記,管理這一流程的程式仔細地檢查相同記錄的更新情況(這些更新可能相互衝突)。與以前相比,準確、更新的資料能夠以更大的數量、在利用更少手動操作的情況下流嚮中央資料庫。
由於我們的資料庫是 Companion 資料庫,它從一些其他的大型資料庫中藉用欄位和資料。Companion
資料庫中每個欄位的名稱都以一個字母的程式碼作為首碼,該程式碼表示其源資料庫。由於強制在每個表的每個欄位名中識別資料源,因此不會漏掉進行同步的機會。
![]() |
學到的教訓以及對開發人員的建議
Kardasz 的團隊從這一正在進行的項目中所學到的主要教訓如下:
![]() |
我們認為,本文中所描述的開發模型的使用範圍是無限的。總而言之,該模型包括了保持核心同步資料的伴隨資料庫、多層應用程式結構、半獨立的模組式開發、為新模組提供框架的核心安全元件、全部範圍的
Oracle 安全特性(特別是 FGAC)以及 PHP
編程的快速和可靠性。我們強大的中央資料庫的功能、準確性和相關性得以增強,而在每次發佈新的模組時,都在俱有最少邏輯障礙的情況下為使用者新增功能。總的說來,最令人滿意的是,它為使用者提供非常良好的服務並且技術支援很易於管理。