目錄
9.3.5 服務器端腳本(server-side scripting)
第九章 應用設計與開發
9.1 應用程序和用戶界面
一個典型的應用程序包括:一個處理用戶界面的前端+一個和數據庫通信的後端+一個包含業務邏輯的中間層:
客戶端-服務器架構(胖客戶端):應用程序在用戶的機器上運行並訪問中央數據庫
- 缺點,升級比較困難,用戶需要安裝應用程序
基於web的應用程序:瀏覽器作爲前端+應用程序作爲後端
web瀏覽器已經成爲通用前端,它通過互聯網連接後端。
web瀏覽器使用一種標準的語法:超文本標記語言(HyperText Markup Language,HTML)標準,既支持信息的格式化顯示,也支持基於表格的界面的創建。
9.2 web基礎
9.2.1 統一資源定位符
統一資源定位符(Uniform Resource Locator, URL)是web上每個可訪問文檔在全球唯一的名字。
URL由三部分組成:
- 第一部分:表示文檔如何被訪問。http表示超文本傳輸協議(HyperText transfer protocol, HTTP),是一個傳輸HTML文檔的協議
- 第二部分: www.acm.org,表示web服務器的機器名稱/地址
- 第三部分:其餘部分是文件在機器上的路徑名,或者文檔在機器中的唯一標識
9.2.2 超文本標記語言HTML
HTML有很多標籤,<html><body><table><form>
HTML還支持樣式表(stylesheet),它可以改變如何展示HTML格式化結構的默認定義,以及其他顯示屬性。
層疊樣式表(Cascading Stylesheet, CSS)標準允許同一個樣式表用於多個HTML文檔,使得一個web站點上的所有頁面具有獨特而統一的樣式。
HTTP定義了兩種請求:get請求和post請求。
9.2.3 web服務器和會話
web服務器(web server)是運行於服務器上的程序,它接收來自web瀏覽器的請求,並以HTML文檔的形式返回結果。瀏覽器和Web服務器通過HTTP通信。
通信協議:web服務器 --GGI協議-- 引用服務器 ---ODBC,JDBC協議-- 數據庫服務器
- 公共網關接口CGI(Common Gateway Interface, CGI)標準:定義了Web服務器與應用程序服務器通信的協議。
- 應用程序通常通過ODBC, JDBC或者其他協議與數據服務器進行通信,以獲取或存儲數據
三層web應用體系結構 和 二層web應用體系結構:
- 三層結構:web服務器+應用服務器+數據庫服務器。
- 缺點:增加了系統的開銷;CGI接口爲每個請求都開啓一個新的進程爲之服務,這導致更大的開銷
- 兩層結構:應用程序作爲Web服務器本身的一部分+數據庫服務器
對比客戶端與web服務器的連接-與-數據庫服務器連接的區別?
- 客戶端與Web服務器的連接:它們之間不存在持續的連接,當web服務器接收到一個請求時,臨時創建一個連接以發送請求並解釋偶來自web服務器的響應。但是連接可能會關閉,且下一個請求可以生成一個新的連接。
- HTTP協議是無連接的(connectionless)。原因是:大多數計算機能同時接納的連接數目有限,如果web中大量的站點對單臺服務器建立連接,就會超過限制,拒絕後續的服務。而使用無連接協議,當滿足請求時連接可以立刻斷開,爲其他請求留出空間。
- 會話:大多數的web應用需要會話信息,以允許有意義的用戶交互。
- 例如:應用程序需要認證用戶。每次會話應進行一次驗證,會話中的交互不需要重新認證。
- 儘管連接會關閉,但是爲了實現會話,可以在客戶端存儲額外的信息,並隨着會話中每個請求返回;服務器使用這個信息來辨別出請求時用戶會話的一部分。關於會話的額外信息也同樣需要存儲在服務器端維護。——這種額外信息以網絡跟蹤器(cookie)的方式存儲在客戶端。
- Cookie——一個cookie是一段包含關聯信息的文本,並關聯一個名字。一個域(站點)只能獲取到它自己設置的cookie,而不能得到其他站點設置的cookie,而且cookie可以跨域複用。
- 例如:google.com可能設置一個名爲prefs的cookie。
- 對於每一個請求,google.com都能從用戶的瀏覽器中得到這個名爲prefs的cookie,然後根據指定的偏好展示結果。
- 例如:google.com可能設置一個名爲prefs的cookie。
- 爲了跟蹤用戶會話的目的,應用程序可能會產生一個會話標識符(通常是一個當前沒有用作會話標識符的隨機數),然後發送給包含這個會話標識符的名爲比如sessionid的cookie。該會話標識符也保存在服務器本地。
- 當請求進來時,應用服務器向客戶端請求名爲sessionid的cookie。
- 如果客戶端沒有該cookie,或者返回的值不是當前在服務器中記錄的有效會話標識符,應用程序認爲該請求不是當前會話的一部分。
- 如果cookie的值與一個存儲的會話標識符匹配,則該請求就被識別爲有一個進行中的會話的一部分。
- 當請求進來時,應用服務器向客戶端請求名爲sessionid的cookie。
- 如果一個用戶需要安全的鑑別用戶,則它只能對用戶進行認證之後再設置cookie,例如:輸入正確的賬戶和密碼之後才通過認證。
- 對於高安全要求的應用,服務器可能會在有效期之後/或用戶註銷時使會話無效。
- 對於低安全要求的應用,cookie可能永久存儲在瀏覽器和服務器中,它們識別出用戶對同一網站的後續訪問,而不需要輸入任何驗證。
- ODBC和JDBC與數據庫服務器的連接:會創建一個會話,且會話信息保留在服務器和客戶端,直到會話結束——信息包括該用戶的用戶標識符和用戶已設置的會話參數等。
9.3 servlet和JSP
Java servlet規格說明定義了一種web服務器與應用服務器間通信的應用程序編程接口。
Java HTTPServlet是Servlet API的具體實現。
當服務器啓動/服務器收到遠程的HTTP請求指定訪問某個特定的servlet時,servlet的代碼被加載到Web服務器中。servlet的作用是處理這些請求,並生成HTML頁面返回給客戶端瀏覽器的請求。
9.3.1 一個servlet的例子
servlet對HTTP請求動態生成響應。
每次請求都會生成一個新的線程,在線程中執行調用,因此多個請求就可以並行處理。
請求和輸出:HttpServletRequest,HttpServletResponse
9.3.2 servlet會話
瀏覽器和web服務器之間的交互是無狀態的。
cookie可以用來識別一個請求是否與前一個請求來自同一個瀏覽器會話。
servlet API提供了跟蹤會話和存儲會話相關信息的方法。
HttpServletRequest.getSession(false)獲取發出請求的瀏覽器session(設置爲true表示請求時新請求時,必須創建新的會話對象)。
- 當getSession()被調用時,服務器會要求客戶端返回具有指定名字的cookie;如果客戶端沒有該cookie,或者返回的cookie與任何進行中的會話都不匹配,則getSession()返回空值,並且servlet會將用戶指引到一個登錄頁面。
- 登錄成功後,servlet會執行getSession(true)返回一個新的會話對象。
- 爲了創建一個新的會話,web服務器內部執行以下任務:
- 在客戶端瀏覽器設置cookie,用會話標識作爲它所關聯的值。
- 在服務端創建一個新的會話對象,並將會話標識符的值與會話對象關聯。
- 爲了創建一個新的會話,web服務器內部執行以下任務:
9.3.3 servlet的生命週期
servlet的生命週期由web服務器控制。
當客戶端請求特定的servlet --> 服務器檢查是否存在該servlet實例
-->如果不存在,web服務器就將servlet類加載到JVM中,並創建servlet類的一個實例;並且Web服務器調用init()方法,初始化該實例。注意:每個servlet實例僅在加載的時候初始化一次
--> 確定servlet實例存在後,Web服務器調用servlet的service()方法,並以一個request和response對象作爲參數。默認情況下,服務器啓動一個新的線程執行service()方法。
--> 當不再需要servlet時,調用destroy()方法停止一個servlet。服務器可以設置當多長時間沒有對某個servlet的請求,就自動停止它。
9.3.4 servlet支持
許多應用服務器都提供servlet的內嵌支持,如tomcat,jboss等。
除了servlet支持之外,應用服務器還提供許多其他的服務:
- 允許應用程序部署或者停止
- 提供監視應用服務器狀態的功能
- 監測代碼的變化,並透明的重新編譯和加載servlet
- 支持多臺服務器在多臺機器上並行運行,以提高性能,並將請求分發至適當的機器上
- 有的還支持J2EE平臺
9.3.5 服務器端腳本(server-side scripting)
服務器端腳本:可以嵌入到HTML文本中。
服務器在傳送Web頁面之前,先執行嵌入到HTML頁面內容中的腳本(可能會修改頁面),再講腳本的源代碼刪除,因此客戶端察覺不到這些腳本。
常見的服務器端腳本語言:
JSP - Java Server Pages:允許Java嵌入到HTML中。嵌入的部分允許動態的生成HTML。
- JSP腳本實際上轉換爲servlet代碼進行編譯,用<%....%>嵌入到HTML中
- JSP也支持標籤庫(tag library)的概念,允許使用標籤,JSP的標準標籤集定義了變量和控制流、以及基於JS的表達式語言,都在服務端解釋。
PHP - <?...?>嵌入到HTML中。類似於JSP。
9.3.6 客戶端腳本
客戶端腳本語言(client-side scripting language): 用於客戶端的web瀏覽器上執行的語言。例如:JavaScript語言
JavaScript:
- 可以用於輸入驗證
- 可以用於動態修改所顯示的HTML代碼
瀏覽器將HTML代碼解析爲內存中的一個樹結構,它是由文檔對象模型(Document Object Model,DOM)標準定義的。
JS代碼可以修改該樹結構。
雖然JS代碼已經標準化,但是瀏覽器之間存在差別,特別是DOM模型的一些細節。也因此會存在JS兼容性的問題。
爲了避免這種問題,最好使用一個JS庫,該庫可以獨立於瀏覽器。例如:Yahoo的YUI庫。
Ajax技術:可以使得客戶端與web服務器異步通信,不阻斷用戶與瀏覽器的交互,並能夠獲得數據的顯示。
9.4 應用架構
模型-視圖-控制器(Model-view-Controller, MVC)架構:
- 模型:對應於下文的業務-邏輯層
- 視圖:定義數據的展示
- 控制器:接受事件(用戶操作),在模型上執行操作,並返回一個視圖給用戶
爲了處理大型應用的複雜性,通常將它們分層:
- 展示層/用戶界面層: 處理用戶交互。單個應用程序可能有若干個不同版本的展示層,對應於不同類型的界面,例如:web瀏覽器以及手機用戶界面
- 業務邏輯層:提供對數據和數據操作的高級視圖
- 提供實體的抽象,以及對其的操作以保證業務規則(business rule)
- 業務邏輯包含工作流(workflow)
- 數據訪問層:提供業務邏輯層和底層數據庫間的接口。
- 如果底層數據庫是關係數據庫,可以使用面嚮對象語言編寫業務邏輯層,並使用面向對象數據模型。這種情況下,數據訪問層還提供從業務邏輯所用的面向對象數據模型到數據庫所支持的關係模型的映射。
下圖展示了處理web瀏覽器一條請求所採取的一系列步驟。
1. 應用服務器接收請求 -> 2. 控制器向模型發送請求 -> 3. 模型使用業務邏輯處理請求 -> 4. 模型處理請求時可能需要通過數據訪問層和DB進行交互-> 5. 模型將結果返回給控制器 -> 6. 控制器調用視圖對模型返回的結果生成HTML視圖-> 7. 視圖將生成的結果返回給控制器 -> 8. 控制器將視圖返回給瀏覽器進行展示
9.4.1 業務邏輯層-略
9.4.2 數據訪問層和對象-關係映射
業務邏輯層和數據庫使用相同的數據模型,而數據訪問層只是隱藏了由於數據庫連接的抽象。
面向對象數據庫(object-oriented database):存儲對象和對象之間關係的數據庫。
關係型數據庫:
- 對象-關係映射(object-relational mapping): 將數據庫的數據映射到內存中存儲的對象,以及反向映射,從而將更新後的對象以關係的形式保存回數據庫。
- Hibernate可以將Java對象映射到關係。
- 將Java類映射到數據庫中的一個關係
- properties文件可以記錄數據庫的信息,如:地址、用戶名和密碼
- 支持將聯繫映射爲關聯對象集合的能力
- Microsoft業開發了一種數據模型,叫做實體數據模型(Entity Data Model)以及一個相關框架ADO.NET。
- 它能在實體數據模型和關係數據庫間映射數據
9.4.3 Web服務
web服務(web service)的兩種實現方法:
- 代表性狀態傳輸(REpresentation State Transfer, REST): 通過在應用服務器對URL的標準HTTP請求執行web服務函數調用。應用程序執行該請求並返回結果。可接受和返回JSON或XML格式的對象。
- 有許多Rest風格的web服務器應用
- 大Web服務(更復雜):它對參數和結果使用XML編碼,使用一種專門的語言正規定義Web API,並在HTTP協議上構建了一個協議層。
9.4.4 斷連操作
應用支持當一個客戶端從應用服務器段開時仍支持某些操作。例如:保存用戶輸入到一半的申請表。
這類應用需要在客戶端機器中本地存儲,最好是以數據庫的形式。
Gears軟件是一個瀏覽器插件,它提供一個數據庫、一個本地web服務器,並支持在客戶端並行執行JS。支持跨平臺/瀏覽器操作。
Adobe的AIR軟件也可以提供類似的功能。
9.5 快速應用開發
爲了減少編寫用戶界面的工作量,有以下幾種方法:
- 提供一個函數庫,以最小的編程量生成用戶界面元素
- 在IDE中提供拖放功能,允許將用戶界面元素拖拽到頁面的設計視圖。
- 根據聲明規範自動生成用戶界面的代碼
這些作爲快速應用開發工具(Rapid Application Development,RAD)的一部分用於創建用戶界面。
9.5.1 構建用戶界面的工具
菜單可以通過數據庫的數據生成。
輸入的驗證控件。
顯示查詢的結果集。
分頁展示大的結果集。
JSF框架可以支持上述所有功能。
Microsoft的ASP以及ASP.NEt是JSP/JAVA的一種替代品。
9.5.2 Web應用架構
9.5.3 報表生成器
報表生成器是從數據庫生成人們可讀的概要報告的工具。它將生成格式化文本和概要圖表由於查詢數據庫結合在一起。
需多廠商都提供報表生成工具:Crystal Report和Microsoft(SQL server reporting services)。
報表可以定製、重新執行和更新、以及生成交互式報表。
9.6 應用程序性能
應用程序開發人員可以利用緩存加快處理單個請求的速度,並通過使用多個應用服務器進行並行處理。
9.6.1 利用緩存減少開銷
多種緩存技術可以充分利用事務之間的共性:
- 連接池(connection pooling):
- 解決痛點:創建一個新的JDBC或ODBC連接耗時很長,爲每個請求創建一個新的連接不合適。
- 工作原理:
- 連接池管理器(應用服務器的一部分)創建一個打開的ODBC/JDBC連接的池並對其進行管理。
- 當一個新的請求過來,並向連接池申請一個連接,用完之後再將連接歸還。
- 如果申請連接時,連接池內無空閒連接,那麼打開一個新的連接(此時要注意不要超過數據庫能支持的最大連接數)
- 如果打開的連接長時間未用,連接池管理器可以關閉一些打開的數據庫連接。
- 許多應用服務器以及較新的ODBC/JDBC驅動程序提供內置的連接池管理器。
- 注意:程序員一定要記得關閉一個打開的JDBC連接(或者將其歸還給連接池)。因爲數據庫可支持的連接數目有限,並且程序不會自動關閉或者歸還JDBC連接,這樣很容易導致超過數據庫能夠支持的連接上限。
- 通過緩存響應一個請求所發送的最終web頁面/查詢結果可以進一步減少開銷
- 只要數據庫的查詢結果不變,就可以緩存之前的結果並重用他們。減少數據庫通信的開銷。
- 緩存的查詢結果和緩存的web頁面是物化視圖的形式
- 如果底層數據庫改動,緩存就需要被重新計算或增量更新
- 例如Microsoft SQL Server會爲應用服務器提供一種註冊查詢,並在查詢結果發生改變時從數據庫得到通知(notification),以確保查詢結果是最新的。
- 如果底層數據庫改動,緩存就需要被重新計算或增量更新
9.6.2 並行處理
並行運行多個臺服務器可以處理非常重的負載。
一個請求可以被web服務器/網絡路由器路由到其中的一臺應用服務器。來自特定客戶端會話的請求必須送到同一臺應用服務器進行處理,因爲要維持客戶端會話的狀態。底層數據庫被多臺應用服務器共享。
- 瓶頸:數據庫共享==> 可以儘可能緩存結果,減少數據庫請求;使用並行數據庫系統
9.7 用於程序安全性
本節介紹幾種安全漏洞,安全認證和細粒度授權技術,以及審計追蹤(幫助從未經授權的訪問和錯誤更新中恢復)
9.7.1 SQL注入
SQL注入(injection):攻擊者設法獲取一個應用程序來執行攻擊者生成的SQL查詢。
解決方案:採用預備語句執行SQL,使得程序會自動轉義特殊字符,
例如:
// SQL注入方式1:採用字符串拼接生成SQL ==> 可以使用預備語句執行SQL
String query = "select * from student where name like '%'"+name+"'%'";
// 若name = ";<some SQL statement>;--"
// 會導致第一個查詢結束後,執行嵌入的第二個sql,而後面的百分號會被註釋掉==》產生安全問題
// SQL注入方式2:==> 可以在拼接之前驗證orderAttribute是否屬於takes的屬性
String query = "select * from takes order by" +orderAttribute';
9.7.2 跨站點腳本和請求僞造
跨站點腳本(Cross-Site scripting,XSS)攻擊:
例如:一個網站允許用戶輸入評論或姓名的文本,將其保存後可以顯示給其他用戶看。
一個惡意用戶並不輸入一個有效的文本輸入,而是輸入如JS或Flash的客戶端腳本語言編寫的代碼。
當另一個用戶閱讀輸入的文本時,瀏覽器將會執行腳本,它可能會進行一些操作,如:將私人cookie發送給惡意用戶。
若恰巧該腳本執行的時候用戶登錄了銀行賬戶,該腳本可能將有關銀行登錄的賬戶信息的cookie發給惡意用戶。
惡意用戶使用這個cookie,可以連接到銀行的web服務器,欺騙它相信連接的仍是原用戶。
跨站點請求僞造(Cross-site Request Forgery,XSRF或CSRF):
事實上,上述例子中該腳本也可以被設計爲設置適當參數並訪問銀行網站的適當網頁執行轉賬。
假定URL接受了指定的參數,並進行轉賬,這種漏洞就是CSRF。
例如:
<img src="http://mybank.com/transfermoney?amount=1000&toaccount=14325"/>
預防措施:
- 防止你的網站被用來發動XSS或XSRF攻擊
- 禁止用戶輸入的任何文本中的任何HTML標籤。存在檢查或去除這些標籤的函數
- 缺點:要小心處理,否則可能會導致顯示錯誤
- 防止你的站點被其他站點發動的XSS或XSRF攻擊
- 爲了避免用戶已經登錄你的網站,並訪問了一個易受XSS攻擊的網站,在該用戶的瀏覽器上執行惡意代碼來對你的站點進行操作。可以嘗試一下幾個步驟減少風險
- HTTP協議允許一個服務器檢查訪問頁的引用頁(referrer),即:用戶爲了初始化訪問頁而點擊的鏈接所在的網頁的URL。通過檢查引用頁是否有效,如:引用頁URL是否是同一個網站的網頁,源自用戶訪問的不同網頁上的XSS共計可以防止。
- 除了使用cookie,還可以將會話限制在原始驗證它的IP地址上。這樣惡意用戶得到cookie,也不可以從另一臺計算機登錄
- 堅決不用GET方法執行任何更新,這防止了<image src...>類的共計。
- 爲了避免用戶已經登錄你的網站,並訪問了一個易受XSS攻擊的網站,在該用戶的瀏覽器上執行惡意代碼來對你的站點進行操作。可以嘗試一下幾個步驟減少風險
9.7.3 密碼泄露
問題:不要在應用程序代碼中明文保存密碼。
解決方案:許多應用服務器提供用編碼的方式保存密碼的機制,在傳送給數據庫之前服務器對其解碼。去除了在應用程序中將密碼另存爲明文的需要。當然,要保證密鑰的安全。
數據庫服務器應該限制能夠訪問它的請求的IP地址,爲其添加白名單。從除了應用服務器端之外的其他網絡地址企圖連接數據庫會被拒絕。
這樣,除非非法用戶登錄了應用服務器,否則即使他們獲得了數據庫的賬戶和密碼,數據庫服務器也不會允許建立連接。
9.7.4 應用程序認證
認證:指驗證連接到應用程序的人或者軟件的身份。
認證的形式:
- 最簡單的形式是由密碼組成。
- 缺點:密碼容易泄露
- 雙因素認證(two-factor authentication):採用兩個獨立的因素(即信息或程序的片段)來識別用戶。這兩個因素不應該具有相同的弱點,例如:採用兩個密碼的方式,兩個密碼可能以相同的方式泄露出去。
- 第一個因素:密碼
- 常用的第二個因素:
- 通過USB接口連接的智能卡或其他加密設備,可基於加密技術進行認證。一次性密碼設備,每分鐘生成一個新的隨機數。
- 給用戶一個設備,爲了驗證,用戶需要輸入設備生成的數字和密碼
- 每個設備生成不同的僞隨機數序列。
- 應用服務器能夠生成與用戶設備相同的僞隨機數序列,在認證時在將顯示的數字處停下來,並驗證是否匹配。
- 該方案要求設備中與服務器端的時鐘始終是合理緊密的同步。
- 當用戶想登陸時,給用戶的註冊手機發送一條包含一次性密碼的短信。
- 通過USB接口連接的智能卡或其他加密設備,可基於加密技術進行認證。一次性密碼設備,每分鐘生成一個新的隨機數。
- 缺點:仍然會受到中間人(man-in-the-middle)攻擊。
-
- 這種攻擊中,一個試圖連接應用的用戶被轉向一個虛假網站,它接受用戶的密碼,包括第二因素密碼,並立即你用該密碼到原始應用中認證。
-
當用戶訪問多個網站時,需要分別在每個網站上做認證而感到不快。所以系統可以允許用戶向一箇中央認證服務進行認證,並且其它網站和應用也可以通過中央認證服務器進行認證,於是相同的密碼可以用於訪問多個站點。
- LDAP協議:廣泛的用於這種中央認證點;一些機構實現了包含用戶名和密碼信息的LDAP服務器,並且應用程序使用LDAP服務器對用戶進行認證。
單點登錄(single sign-on):系統允許用戶只驗證一次,且通過一個認證服務對用戶的身份進行驗證的多個應用都不需要再次認證。
- 安全斷言標記語言(Security Assertion Markup Language, SAML):是一個在不同安全域間交換認證和授權信息的標準,已提供跨機構單點登錄。例如:一個應用需要提供對一所特定學校(如耶魯)的所有學生的訪問權限,該學校可以建立一個基於web的服務實施認證。假設一個連接到該應用的用戶具有用戶名[email protected]。則該應用將該用戶轉向耶魯大學的認證服務對其認證,而不直接對其認真,並告訴該用戶是誰且可能提供一些額外的信息。該用戶的密碼以及其他認證因素不會顯示給應用,並且用戶也不需要應用程序顯示的註冊。不過當認證用戶時,應用程序必須信任學習的認證服務。
- OpenID標註:是另一種跨機構單點登錄的標準。許多流行的站點,如google是OpenID認證提供方。任何作爲OpenID客戶端的應用程序可以使用這些提供方中的任意一個來認證用戶。
9.7.5 應用級授權
SQL授權模型的不足:
SQL授權模型對用戶授權的管理是非常有限的。例如:限制所有學生只能看到自己的成績。
這樣的授權無法再SQL中表示,因爲:
- 缺乏最終用戶信息。
- 數據庫範根主要來自web應用服務器,最終影虎在數據庫本身上通常沒有個人用戶標識
- 缺乏細粒度的授權
- 授權在單挑元組的級別在目前的SQL標準中是不可能的。SQL標準只允許在整個視圖、關係或指定屬性授權。
- 方法1:理論上可以通過建立該學生成績的視圖,繞過限制,但是實現起來非常繁瑣和不切實際。
- 方法2:令create view studentTakes as select * from takes where takes.ID = syscontext.user_id()、但是這種方法只適用於學生,老師需要不同的視圖。開發和維護更復雜。
應用程序級別的授權:
目前,授權的任務全部由應用程序執行,繞過SQL限制。
在應用級別,授權用戶訪問特定接口,並可能進一步被限制只能查看或更新的某些數據項。
雖然很靈活,但是也有缺點:
- 授權代碼和應用程序的其它代碼混合在一起
- 可能會存在漏洞,因爲應用程序具有一個非常大的”表面積“,保護起來很艱難;而SQL級別的授權表面積會很小。
Oracle提供了細粒度的授權機制,例如oracle的虛擬私有數據庫(Virtual Private Database, VPD)。
它允許系統管理員將一個函數關聯一個關係,該函數返回一個謂詞,該謂詞必須加入到任何一個使用該關係的查詢中。例如:謂詞ID = sys_context.user_id()需要加到takes的查詢的where子句中。
===> 進而提供了行級授權(row-leve authorization)
缺點:輸出可能並不是我們想要的結果。如果查詢的目的是查找班級成績的平均值,那麼該用戶最後得到的職能制自己的平均成績。
9.7.6 審計追蹤
審計追蹤(audit trail)是關於應用程序數據的所有更改的日誌,以及一些信息,如:那個用戶執行了更改和什麼時候執行的更改。其作用包括:
- 可以在程序安全性被破壞或者發生錯誤更新時,(a)幫助確定發生的動作以及操作執行人,並且(b)幫助修復安全漏斗或錯誤更新所帶來的損失。
- 用於探查安全漏洞
數據庫內置的審計追蹤通常對於應用程序來說是不夠的,因爲它們無法追蹤應用程序的最終用戶。它只能追蹤低級別記錄的更新(即關係中的元組),而無法在較高級別(如業務邏輯級別)進行追蹤。
===>因此,應用程序也要創建一個較高級別的審計追蹤器。
9.7.7 隱私
數據隱私非常重要!已經有法律來保護隱私數據。
聚集的隱私數據的價值很重要。例如:檢查藥物副作用。
web站點如何保護收集到的個人信息 - 很重要!
9.8 加密及其應用
數據庫方面,加密可以可用來以一種安全的方式存儲數據,從而即使數據被一個未經授權的用戶獲取,如果沒有揭祕祕鑰的話數據也無法被訪問。
許多數據庫都會對客戶敏感信息進行加密。許多法律也要求數據庫必須對敏感信息進行加密存儲。
9.8.1 加密技術
一個好的加密技術具有的特性:
- 對於授權用戶,加密數據和解密數據相對簡單
- 加密模式不應依賴於算法的保密,而應該依賴於被稱作加密密鑰的算法參數,該密鑰用於加密數據。
- 在對稱密鑰(symmetric-key)加密技術中,加密密鑰也用於解密數據。
- 在公鑰加密(public-key)(也稱作非對稱密鑰(asymmetric key)加密技術)中,存在公鑰和私鑰,分別用於加解密數據。
- 對入侵者來說,即使他已經獲得加密數據的訪問權限,確定解密密鑰仍是機器困難的。在非對稱密鑰加密的情況中,即使有公鑰,推斷出私鑰也是極其困難的、
擴展機密標準(Advanced Encryption Standard,AES)是一種對稱密鑰加密算法
- 該標準基於Rijindael算法-每次對一個128位的數據庫操作,密鑰的長度可能是128.192或256位
對稱加密算法的缺點:
- 對於任意對稱密鑰加密模式的使用,授權用戶通過一個安全機制得到加密密鑰。這是其一打弱點,因爲模式的安全不高於加密密鑰傳輸機制的安全。
公鑰加密算法:存在一個public key和一個private key,公鑰是公開的,私鑰是隻由擁有它的用戶知道。使用公鑰進行加密,私鑰進行解密。
9.8.2 數據庫的加密支持
數據庫加密的不同級別:
- 較低級別:對存儲數據庫數據的磁盤塊進行加密
- 可以抵禦能訪問磁盤內容但不能訪問密鑰的攻擊者
- 當從磁盤上獲取一個磁盤塊時,先解密再以平常的方式使用
- 較高級別:對指定屬性進行加密。
- 不同的屬性可以使用不同的密鑰。
- 數據庫通常不允許加密主碼、外碼、屬性上的索引的加密。
- 此外,還要使用額外的隨機數防止字典攻擊
爲了訪問數據,還需要解密密鑰。
-
- 單個主加密密鑰可以用於所有的加密數據
- 不同屬性的解密密鑰存在一個文件或關係中(稱爲錢夾),它本身也用主密鑰加密。
一個需要訪問加密屬性的數據庫的連接必須提供主密鑰,除非提供了主密鑰,否則該連接將無法訪問加密數據。主密鑰保存在應用程序中,或者由數據庫用戶記住,並在用戶連接到數據庫時提供。
數據庫級別加密的優點:時空開銷相對較小,對應用程序的修改較小。
應用級別的加密:
數據發送到數據庫之前由應用程序加密,數據取回時應用程序對其解密。
缺點:應用程序的代碼需要做大量修改。
9.8.3 加密和認證
基於密碼的認證容易被竊聽。
一個較爲安全的機制包括詢問-回答(challengE-Response)系統。
其過程爲:
- 數據庫發送一個詢問字符串給用戶 --- 該字符串經過公鑰加密
- 用戶用一個密碼作爲加密密鑰對詢問字符串進行加密,然後返回結果
- 數據庫系統用同樣的密碼把字符串解密,並檢查解密結果是否與發送的詢問字符串一致 來驗證用戶的身份。
優點:確保沒有密碼在網絡上傳輸
公鑰系統也可以用於詢問-回答(challengE-Response)系統。
其過程爲:
- 數據庫系統使用用戶的公鑰加密詢問字符串,並把其發給用戶
- 用戶用他的私鑰對字符串解密,並把結果返回給數據庫系統
- 數據庫系統驗證該結果是否與發送的詢問字符串一致,來進行驗證
優勢:不在可能被系統管理員看到的數據庫中存儲密碼
用戶的私鑰存儲在計算機上是有風險的,如果該計算機收到攻擊,私鑰可能會暴露。
==>智能卡(smart card):解決這一問題。密碼可以存儲在一塊嵌入的芯片中;智能卡的OS保證該密碼絕不會被讀取,但是允許數據被髮送到卡上進行加密或者解密。
9.8.3.1 數字簽名
公鑰機密的另一個應用 —— 數字簽名(digital signature):用來驗證數據的真實性。
私鑰對數據”簽名“(加密),且簽名後的數據可以公開。
所有人都可以用公鑰對簽名進行解密,來驗證簽名。===>認證(authenticate)該數據是由聲稱創建該數據的人創建;
9.8.3.2 數字證書
通常認證是一個雙向的過程,交互實體要互相向對方認證自己的身份。防止惡意站點冒充合法站點。==> 數字證書(digital certificate)。
用戶與Web站點A交互,需要獲取到A的公鑰;站點B可以僞裝成站點A,提供B的公鑰。那麼如何判斷A公鑰和B公鑰哪個是真實的呢?
==> 引入 數字證書(digital certificate):
- 公鑰由一個公開的認證機構簽名。例如:根認證機構的公鑰保存在標準的web瀏覽器中,它們簽署的證書可以使用保存的公鑰來驗證。
- 兩級系統 會給跟認證機構帶來創建證書這一巨大負擔 ==> 採用多級系統取而代之。
- 採用多個根認證機構,每個根認證機構下有一顆認證機構樹。每個機構(除根機構)都有其父機構簽署的一個數字證書。
認證機構A簽署的證書包括:
- 公鑰KA
- 一個可以用公鑰KA解密的加密文本E
- 證書籤發給的機構及它的公鑰KC
- 若A不是根驗證機構,還包括其父認證機構簽發給A的數字證書,這個證書認證了密鑰KA本身
驗證一個證書?
- 加密文本E通過KA解密,從而獲得團體名稱;
- 如果A不是根驗證機構,其公鑰KA會遞歸的使用E中包含的數字證書進行驗證,直至抵達根機構簽發的證書
HTTPS中應用數字證書:
- 站點向瀏覽器提供它的證書,瀏覽器將證書顯示給用戶,如果用戶接受該證書,瀏覽器則使用提供的公鑰進行加密。
- 惡意站點可以對數據進行加密,但是無法解密;只有擁有相應私鑰的站點才能解密瀏覽器發送的數據。
- 由於公鑰/私鑰加密算法代價遠高於對稱加密,爲了減少呆極愛,HTTPS實際是在認證之後創建一個一次性的對稱密鑰,在隨後的會話中採用這個密鑰對數據加密。
總結
- 目前,大多數應用程序都使用Web瀏覽器作爲它們的前端,數據庫作爲後端,以及一個應用服務器介於中間
- HTML提供了定義超鏈接和表單功能結合的界面的能力。Web瀏覽器通過HTTP協議和web服務器通信、web服務器可以將請求傳遞給應用程序,並將結果返回瀏覽器。
- web服務器執行應用程序以實現所需的功能。servlet是一個使用廣泛的機制;另外還有服務器端腳本語言。
- 客戶端腳本語言 - JS使用最爲廣泛——在瀏覽器端提供更豐富的用戶交互
- 複雜的應用程序通常具有多層架構:
- 實現業務邏輯的模型、控制器以及用戶顯示結果的查看機制
- 它們還包括一個實現了對象-關係映射的數據訪問層
- 目前已經有很多工具用於快速應用開發,特別是減少構建用戶界面所需的工作
- 多種形式的緩存(連接池和查詢結果緩存)+並行處理技術 ==> 用來提高應用程序性能
- 應用程序要注意安全性問題,以防止受到攻擊:SQL注入攻擊、跨站點腳本攻擊等
- SQL授權機制是粗粒度的,對處理大量用戶的應用具有有限的價值。目前,應用程序在數據庫系統之外實現了細粒度的、元組級別的授權,以處理大量應用程序用戶。提供元組級別的空值和處理大量應用程序用戶的數據庫已經開發出,但是還沒有成爲標準
- 保護數據的隱私 - 非常重要。有法律保護隱私數據
- 加密:在保護信息以及認證用戶和web站點中版一樣了關鍵角色。對稱祕鑰加密和公鑰加密是兩種相對但廣泛應用的加密方法。許多法律規定對敏感數據加密是必須的。
- 加密還在爲應用程序認證用戶,爲用戶認證web站點以及數字簽名中扮演了關鍵角色、