扈 瑋,王立華
(山東科技大學 電子信息工程學院,青島 266590)
電子商務的快速發展對系統的安全性提出了更高的要求,但是許多企業應用的安全性還沒有得到足夠的重視,密碼泄露的情況時有發生,造成了嚴重的經濟損失和社會不安.早在2008年,卡內基梅隆大學軟件工程研究所就通過美國政府資助的漏洞警報系統向安全專業人員發出公告:MD5應被視為已破解且不適合繼續使用的加密方法;網絡公司TrustedSec LLC的首席執行官David Kennedy指出:“MD5被認為在2013年之前就已經過時了.從那時起,大多數公司開始使用更安全的哈希算法”[1].在2019年01月,BMG公司正式確認該公司的熱門游戲《塞勒姆小鎮》有安全漏洞,該漏洞現已得到解決,但該游戲擁有760萬用戶,其信息受到損害.用戶的密碼、IP地址和電子郵件信息有被泄露的風險,而泄密的原因是:使用MD5哈希算法存儲帳戶密碼[2].隨著此類密碼泄露事件的一次次發生,迫切需要更安全的加密算法提高系統的安全性能.
運用MD5加密算法雖然可以實現密碼加密的功能,產生32位字符串并且算法不可逆.但是MD5加密算法存在著諸多弊端:同一密碼經過MD5算法產生的字符串一模一樣;同時隨著計算機技術的發展和計算水平的不斷提高,可以用彩虹表等方法輕松破解,已不再適合安全要求較高的場合使用[3-6].針對此類情況作出改進,旨在設計并實現一個以springmvc+spring+mybatis框架為基礎的電商安全模塊[7-11],其中表現層springmvc框架用于客戶端的視圖顯示;業務層spring框架用于系統業務邏輯操作的具體實現;持久化層框架mybatis用于與Mysql數據庫進行數據交互,完成增刪改查(CRUD)操作.同時用更安全的加鹽Bcrypt算法實現密碼加密和驗證功能,加強了數據安全的維護工作.
Bcrypt算法是基于Blowfish加密設計的一個慢哈希算法,是Open BSD或其他Linux發行版的默認加密算法,該算法的設計是為了抵抗對哈希值或者鹽的布魯特攻擊,有效地解決了MD5加密算法的弊端[12-17].
算法原形是:DK=bcrypt(cost,salt,input)
參數cost是計算強度,即循環次數;
參數salt是密碼學中的鹽;
參數input是輸入的密碼文本;
輸出DK是生成的派生密鑰.
BCrypt算法計算后的密文中包含了算法版本、循環次數、鹽值以及哈希字符串.下面是“123456”以10為循環次數經加鹽BCrypt算法加密后隨機生成的60位字符串“$2a$10$jI49TG.oPta0fuhlxqtLzeUZuw N1rzZU9G/1R1CIYIT.lirNPimwu”.其中$是分割符,無意義;2a表示BCrypt算法加密版本號;10是cost值,表示密碼加密的計算強度,強度越高,則密碼越復雜,計算時間也越長;而后的前22位是鹽值,具有隨機性;其余的哈希字符串就是密碼的密文了.
如果只是單純的哈希字符串存儲,如果兩個或更多人設置的密碼相同,則加密后將得到相同的結果,進入到數據庫破解一個就可以破解一大片的密碼.例如名為A的用戶可以查看數據庫,可以發現存儲的哈希字符串結果有些是相同的,那么不同的用戶對應的就是同一個設置密碼,這樣就可以利用別人的身份登錄系統.由于鹽是隨機產生的,存儲不同用戶數據時加入的鹽都是隨機的,所以就可以保證不同的用戶即使有相同的密碼,存儲在數據庫中的密碼也是千差萬別的.上述加密策略,可以形象地稱為“加鹽哈希加密”[18],可以在對密碼進行哈希算法之后,將鹽隨機并混入加密后的哈希字符串,進行二次加密,驗證時也無需單獨提供之前的鹽,從而無需單獨處理鹽的問題,更加安全方便.
BCrypt是單向的,而且經過salt和cost的處理,與MD5加密算法相比,安全性得到了極大地提高.為使攻擊者難以構造出所有可能值的查詢表,其鹽值和計算強度的值必須足夠長,彩虹表攻擊破解密文的概率則越低,破解的難度也就越大.
在電商安全模塊中,用戶密碼的加密和驗證流程如圖1所示.流程包括用戶注冊和用戶登錄兩大部分[19].有信息系統存在的地方,就需要進行用戶信息認證,還可以根據用戶賦予不同的訪問權限.安全模塊的注冊和登錄的流程大致如下:

圖1 密碼加密存儲與驗證流程圖
(1)用戶注冊:用戶輸入登錄名、密碼及其他有關信息后,將相關數據傳輸到后端服務器,直至保存到Mysql數據庫中.因為登錄名也是主鍵,具有唯一性,若輸入的登錄名已經存儲在數據庫中,則無法成功注冊,仍就停留在注冊頁面并且彈出注冊失敗的提示;
(2)后端服務器接受到用戶數據,將其中的密碼進行加鹽BCrypt算法加密處理.若主鍵不重復,則表單數據和對應的創建日期存儲到數據庫中,頁面跳轉到登錄頁面;
(3)用戶登錄:用戶輸入的登錄名及密碼傳輸到服務器,服務器通過登錄名從mysql數據庫中查詢該用戶是否存在,若用戶不存在,則仍就停留在登錄頁面;
(4)若用戶存在,則服務器將客戶端傳過來的密碼經過BCrypt算法加密處理得到哈希字符串;同時服務器根據登錄名取得數據庫中對應的密文,并提取出鹽值得到哈希字符串;并對兩個哈希字符串進行驗證,如果完全相同,則表示用戶登錄成功,頁面跳轉到用戶主頁;如果不同,則表明用戶登錄失敗,仍就停留在登錄頁面,并且不會給出任何信息提示.
用戶注冊和登錄功能涉及到用戶表tb_user,如表1所示;涉及到的類,如表2表示.
用戶注冊的時序圖如圖2所示,時序圖中涉及到的主要方法介紹:
Add (@RequestBody TbUser user):后端控制層增加用戶信息的方法;

圖2 密碼加密功能時序圖
encode (rawPassword):加密方法,參數rawPass- -word為用戶輸入的密碼;
add (TbUser user):后端服務層增加用戶信息的方法;
insert (user):后端數據訪問層向數據庫增加用戶信息的方法.

表1 用戶表(tb_user)

表2 類的簡介
當用戶在注冊頁面上填寫表單,點擊注冊按鈕后,將依次調用控制類UserController的add (@Requ--estBody TbUser user)方法;BCryptPasswordEncoder的encode (rawPassword)方法,并將加密后的字符串存入user中;服務接口類UserService的add (TbUser user)方法;服務實現類UserServiceImpl的add (TbUer user)方法,并設置申請日期存入user中;數據訪問類TbUser Mapper的insert (user)方法,向數據庫插入表單數據.
在控制類UserController中,如果增加數據成功,Result傳遞的參數為{success:true,message:“注冊成功”},頁面自動跳轉到登錄頁面;如果增加數據失敗,Result傳遞的參數為{success:false,message:“注冊失敗”},頁面仍就停留在注冊頁面.
用戶注冊功能的實現效果圖,如圖3所示.

圖3 注冊功能實現圖
用戶登錄的時序圖如圖4所示,時序圖中涉及到的主要方法介紹:
loadUserByUsername (String username):認證類的驗證方法,參數為用戶輸入的登錄名;
findOne (String id):后端服務層根據id查詢用戶數據的方法;
selectByPrimaryKey (id):后端控制層根據id從數據庫查詢用戶數據的方法;
matches (rawPassword,encodedPassword):密碼驗證方法,參數encodedPassword表示從數據庫讀取的密文.

圖4 密碼驗證功能時序圖
用戶在登錄頁面輸入登錄名和密碼,點擊登錄按鈕之后,依次調用UserDetailsServiceImpl的load- -UserByUsername(String username)方法;UserService- -Impl的 findOne(String id)方法;TbUserMapper的selectByPrimaryKey(id)方法,運用mybatis框架的xml配置文件可以方便地從數據庫中得到主鍵對應的TbUser用戶對象,TbUserMapper.xml文件里對應的查詢語句如下:
<select id= "selectByPrimaryKey" resultMap="BaseResultMap" parameterType= "java.lang.String">
select <include refid= "Base_Column_List"/> from tb_user
where user_id = #{ userId,jdbcType= VARCHAR}
</select>
其中parameterType表示輸入參數是字符串類型,user_id表示用戶輸入的登錄名,Base_Column_List表示主鍵對應的包括諸多字段信息的TbUser用戶對象,resultType表示把查詢結果封裝到pojo類型中.
在UserDetailsServiceImpl認證類中,判斷user對象非空,若不滿足條件則仍是登錄頁面,若滿足條件則在spring-security.xml(安全框架配置頁)的認證管理器模塊引入密碼工具接口的實現類BCryptPasswordE- -ncoder,調用matches(rawPassword,encodedPassword)方法進行密碼驗證,判斷用戶輸入的密碼和從數據庫讀取的密碼是否一致,若不滿足條件則仍是登錄頁面,若滿足條件則跳轉到用戶系統主頁.用戶登錄功能實現效果圖,如圖5所示.
如圖6所示,數據庫存儲的密碼均為123456,xiaoA用戶的密xiaoB用戶和xiaoC用戶的密碼都采用MD5加密算法,產生了相同的32位字符串,存儲到數據庫中.管理員雖然不能直觀看到賬號的密碼,但是同樣的明文經過MD5算法加密產生相同的密文,而且可以用彩虹表等方法輕松破解.采用加鹽BCrypt算法成功解決了以上問題,正如圖中的xiaoD用戶和xiaoE用戶的密碼都采用加鹽BCrypt算法,產生了隨機的60位字符串,存儲到數據庫中,大大提高了數據的安全性.

圖5 登錄功能實現圖

圖6 實現效果圖
現今信息安全形勢不容樂觀,很多企業應用安全性未得到足夠重視,涉及購物的電商企業更應加強信息安全,避免造成不可估量的損失.本文結合高內聚低耦合法則、SSM框架三層架構的思想,詳細闡述了用戶注冊和登錄功能設計與實現過程,采用加鹽BCrypt加密算法實現密碼存儲加密和驗證功能,解決MD5加密算法的弊端,為電商安全提供了一份有效解決方案.