白驚寰, 鄭國英
(上海交通大學 軟件學院, 上海 200030)
本課題是基于一家專注于企業(yè)銷售系統(tǒng)的公司研發(fā)的一個銷售預測管理系統(tǒng)來展開分析的,身份認證是一個驗證真實身份和所聲稱的身份是否一致的一個過程[1]。在身份認證服務里主要包含兩個主要內容,第一是要驗證認證消息來源的可靠性,第二是驗證認證消息中所聲稱的身份的有效性。比如用戶持有某個憑證或生物特征[2](如指紋),我們通過驗證其真實性和唯一性來確認用戶身份。
如今大部分系統(tǒng)都包含多種身份的用戶且訪問的資源不單一,但往往所有用戶的登陸地址是相同的。為了滿足這種業(yè)務需求,我們通常使用單點登錄技術[3,4](Single Sign-On)來實現(xiàn)。單點登陸系統(tǒng)在驗證用戶有效性的同時給用戶進行授權,通過不同的算法策略來賦予每個用戶資源訪問的權限,對于不同權限可訪問的資源往往還需要一個目錄結構對資源進行分類。
身份認證中最嚴重安全問題之一即是口令的安全。根據口令生成器[5](Challenge-Response)使用挑響應的驗證方式進行身份認證可以生成一個可以被唯一確認的用戶特征。用戶是否可以只通過一次口令的驗證,當獲得了相應的授權和憑證后,用戶就能夠自動完成之后所有身份認證過程?這種設計思想需要一些特定的協(xié)議的支持。比如單點登陸協(xié)議Kerberos[6-8],這是一種目前比較流行的單點登錄協(xié)議。
在本節(jié)系統(tǒng)設計部分,根據一些成熟實現(xiàn)案例為理論基礎主要討論銷售預測管理平臺如何實現(xiàn)分布式部署[9,10]的架構設計。
按信息系統(tǒng)安全CIA(Confidentiality-機密性,Integrity-完整性,Availability-可用性)準則,其中涉及到安全認證中信息的完整性[11]。消息認證的目的是確保消息的來源是可靠的,并保證消息沒有被篡改過,此外如果在消息中加上了時間戳則可以保證消息的時效性沒有問題。
消息認證一般有3種方式[12,13],第一種是消息整體進行加密作為認證標示。消息的接受方可以根據消息的檢錯碼來判斷收到的消息是否完整。第二種是根據一個公開的函數(shù)加上密鑰來產生一個固定的值通過這個值進行消息的驗證。
MD5是目前比較流行的一種信息摘要算法,它可以將任意長度的輸入消息轉化為一個128位的大整數(shù),并保證它是不可逆的。其算法流程如圖1所示。
MD5以512位的分組來處理數(shù)據參數(shù),然后再將分組劃分為16個32位的自分組,當消息長度不夠時需要填充信息補滿512位。初始化數(shù)據的時候,我們需要用512位的摘要緩存器A、B、C、D作為參數(shù)的輸入點,算法的核心是4個循環(huán)壓縮的函數(shù)模塊,每個處理模塊由多個步驟完成。組合A、B、C、D四個緩存區(qū)的結果,最終得到了128位的信息摘要。
圖1 MD5算法處理過程示意圖
傳統(tǒng)的單點登錄SSO對用戶驗證的方式是基于一個統(tǒng)一存放用戶賬號和密碼的服務[14]。它無法滿足當業(yè)務復雜的多服務系統(tǒng)身份信息存放服務不唯一時的驗證需求。為了解決以上的問題,本文提出了一種基于票據ticket的新型單點登錄技術的實現(xiàn)方案,用來解決多服務間用戶登錄時的身份驗證、權限控制的問題[15]。
下面我們詳細論述Kerberos安全協(xié)議的一些基本概念[16]。第一認證主體(Principal),在整個Kerberos認證機制中認證主體可以是用戶也可以是服務,或是各種主機和服務器,認證主體一般都包含一個用戶名和密碼。第二是密鑰分發(fā)中心(KDC)這是Kerberos的核心[17]。這項技術得以實現(xiàn)的前提是,在整個通訊環(huán)境中我們必須都信任KDC。第三個概念即為票據(Ticket),我們可以將票據理解為一種記錄,這個票據中往往包含了用戶的標示、會話密鑰、票據的有效期等其他應用相關授權信息。這些信息通常都是加密的。第四認證記錄, 認證記錄是存于KDC的一些近期用戶登錄認證授權的日志記錄。
在集群的設計上我們將對這些模塊分別部署為一個服務,通過前后端分離的設計模式采用無狀態(tài)的請求進行模塊之間的調度,最后實現(xiàn)分布式部署的目標。從技術選型、技術特點以及技術實現(xiàn)三方面對這個問題做詳細的解釋。
身份認證服務的設計重點在于如何生產一個有效的信賴憑證并管理。客戶瀏覽器在系統(tǒng)的某一個服務中成功登錄,并完成了有效性驗證后,其他系統(tǒng)都能夠對該用戶提供系統(tǒng)的信任,那么我們就可以說是完成了對身份認證服務實現(xiàn)的工作。
先從設計的用例圖(圖2)入手,對身份認證服務的需求進行深入挖掘,身份認證服務如圖2所示。
如圖2中身份認證所有服務的身份校驗都需要通過身份驗證服務進行處理。身份校驗服務對應的是整個銷售預測管理平臺的服務提供了用戶新增、用戶更新、用戶刪除的功能接口。如圖3所示。
圖2 身份認證服務用例圖
圖3 身份認證系統(tǒng)-功能結構圖
身份令牌生成算法是基于jdk中提供的MessageDigest工具類來實現(xiàn)的。代碼里我們用實例的digest方法實現(xiàn)。最終我們得到了一個16位的比特數(shù)組。基于這個16位的比特數(shù)組,我們遍歷它并逐位計算它的絕對值,根據這個絕對值我們再計算出其對應的16進制數(shù)。顯然很多時候這個數(shù)字的長度會不足兩位,我們需要在得到的16進制數(shù)前面進行補0的操作。最后將得到的這些字符串相加,我們就可以將16位比特數(shù)組轉化為一個32位的16進制字符串了。具體算法如下:
publicstatic String build(String account, String charset) {
MessageDigest digest = null;
StringBuilder buffer = new StringBuilder();
try {// 輸入賬號如果為空則返回空的身份令牌
if (account == null) {
returnnull;
}// 以MD5的算法來實例化digest
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
// 若實例化digest出錯,則向控制臺輸出錯誤的信息
System.out.println("error msg : " + e.getMessage());
returnnull; }
// 根據實例化的digest用md5算法生成一組byte數(shù)組
byte[] bytes = digest
.digest(account.getBytes(Charset.forName(charset)));
for (bytebs : bytes) {
// 為了保證在byte轉int類型時 不丟失符號位
intc = bs& 0xFF;
if (c< 16) {
buffer.append("0");
}
buffer.append(Integer.toHexString(c));
}
returnbuffer.toString();
}
publicstaticvoid main(String[] args) {
String account = "ShanghaiJiaoTongUniversity";
String str = TokenBuilder.build(account, "UTF-8");
System.out.println(str);
}
}
輸出結果: 52ed5a8f8fcc62dfcef21d8eb9b2d7a7;
考慮到身份令牌是有時效性的,當用戶長時間不進行操作后,他的身份令牌會被銷毀。那么當身份令牌被銷毀后,如果用戶再次訪問身份認證服務器,我們需要給他生成一個新的身份令牌。如果我們只根據賬號來計算,那么用戶永遠只會得到一個相同的令牌,因此我們考慮將賬號結合當前服務器的時間戳組合到一起,以此字符串來生成最新的32位16進制的身份令牌。獲取當前時間戳的算法如下:
publicstatic Timestamp getCurrentTimestamp() {
Date date = new Date();
Timestamp nousedate = new Timestamp(date.getTime());
returnnousedate;}
因為用戶不可能在同一時間點里登錄兩次系統(tǒng),所以我們可以保證用戶賬號加時間戳,結合MessageDigest工具類生成的用戶令牌是能夠滿足系統(tǒng)要求的。
本節(jié)將討論如何實現(xiàn)身份認證服務的MVC設計。本服務將給予輕量級的springMVC、Spring、hibernate框架實現(xiàn)基于MVC架構的身份認證服務。MVC框架的核心是將系統(tǒng)分為視圖層(view層)、業(yè)務邏輯層(controller層)和持久化層(model層)。身份認證服務技術架構圖,如圖4所示。
圖4 身份認證服務技術架構圖
SpringMVC框架用來實現(xiàn)MVC的分離,在業(yè)務邏輯層我們會大量使用spring提供的控制反轉IoC機制,將數(shù)據庫操作交給Spring管理、將服務實例化為javaBean,可以大幅度減少開發(fā)的耦合度,同時也將軟件開發(fā)的可復用性大大提高。持久化層我們選擇用hibernate來實現(xiàn),將數(shù)據庫的表和JavaBean關了起來,通過HQL語言操作數(shù)據庫可以大大提高代碼的可讀性,同時可以避免sql注入攻擊等數(shù)據庫操縱安全的問題。
數(shù)據庫的設計是系統(tǒng)的核心,接下來我們將詳細介紹為身份認證服務提供的表結構。
身份認證服務E-R圖,如圖5所示。
圖5 身份認證服務E-R圖
圖中表明了表t_authuser與表t_app、表t_ahthlogin_log、表t_token_log、表t_authseroperate_log彼此之間的依賴關系。
當用戶訪問一個業(yè)務系統(tǒng)時,業(yè)務系統(tǒng)會去進行業(yè)務系統(tǒng)的應用認證,如果應用認證通過則會進行用戶信息的校驗。用戶信息校驗完成后,身份認證服務會保存一份用戶的token,同時返回一個用戶token到用戶的客戶端。
本論文解決了銷售預測管理系統(tǒng)的統(tǒng)一身份認證的實現(xiàn)方式,在本節(jié)中主要對以上的方案進行測試,以測試數(shù)據來驗證方案的可行性。
身份認證主要功能的測試場景,如表1、表2所示。
其中包括登錄和登錄成功后在Token有效期及失效期內用戶訪問的各種場景。目前測試已經完成,測試結果表明身份認證服務可以滿足需求。
系統(tǒng)的性能測試主要為壓力測試。使用loadrunner測試工具,我們模擬了多個用戶短時間里同時訪問銷售預測管理平臺的情況,并通過測試工具計算出了幾個關鍵數(shù)據:單個用戶最短登錄時間、單個用戶最長登錄時間、用戶登錄平均耗時。
表1 賬號登錄測試用例表
表2 Token有效期內系統(tǒng)訪問測試用例表
當系統(tǒng)處于正常運行狀態(tài)時,我們分別用三組數(shù)據進行了四次測試,可以看到當并發(fā)人數(shù)逐漸增加時,服務器響應的時間也會逐漸延長。如表3所示。
表3 用戶并發(fā)登錄耗時測試結果表
平均訪問時間可以看到增加了負載均衡的系統(tǒng)在處理請求響應的耗時均有大幅度的提升,而且當并發(fā)人數(shù)越多登錄優(yōu)化的作用也就越顯著。從測試數(shù)據我們可以得出結論,在同時訪問人數(shù)閾值在300人的時候,平均登錄時間在3秒以內,能夠滿足需求。
隨著企業(yè)分布式集群的不斷擴大,目前的系統(tǒng)存在著很多需要改進的地方。首先需要考慮的問題是如何實現(xiàn)跨域的基于單點登錄的身份認證服務。在這里分析一下跨域身份認證實現(xiàn)的難點??缬虻膯吸c登錄中用戶和應用服務的雙向認證如何實現(xiàn)?在單個域中通常是1對1的認證關系,即一個用戶在一個系統(tǒng)中只保留一個用戶的憑證。但如何是跨域的單點登錄驗證,由于每個域的服務中都需要保存一個用戶憑證,那么用戶和應用服務的驗證關系將成為N對N的關系。如何簡化這種負責的關系流程進一步要研究的重點方向。