眾所周知,WebService訪問API是公開的,知道其URL者均可以研究與調用。那么,在只允許注冊用戶的WebService應用中,如何確保API訪問和通信的安全性呢?本文所指的訪問與通信安全性包括:
訪問安全性:當前訪問者是注冊合法用戶
通信安全性:客戶端與服務器之間的消息即使被第三方竊取也不能解密
本文安全的基本思路是:
注冊用戶登錄時使用RSA加密
Web API調用參數使用DES加密(速度快)
Web API調用中包含一個身份票據Ticket
Web服務器保存當前Ticket的Session,包括:Ticket、DES加密矢量、注冊用戶基本信息
1 WebService身份驗證
確保注冊用戶的訪問安全,需要如下步驟:1)產生一個當前客戶端機器票據(Ticket);2)請求服務器RSA公鑰(RSAPublicKey);3)使用RSA加密登錄口令及發布DES加密矢量(DESCipherVector)。
1.1 產生客戶端機器票據Ticket
一般而言,可以由客戶端機器根據自己的MAC、CPU序列號等唯一標識產生一個本機器的Ticket字符串票據,其目的是:唯一標識當前客戶端,防止其它機器模仿本客戶端行為。
1.2 請求服務器公鑰RSAPublicKey
客戶端攜帶票據Ticket向服務器請求RSA公鑰RSAPublicKey。在服務器端,一般采取如下策略產生RSA加密鑰匙:
Application_Start時產生一個1024或更長的RSA加密鑰匙對。如果服務器需要長久運行,那么Application_Start產生的RSA可能被破解,替代方案是在當前Session_Start時產生RSA加密鑰匙對
保存當前票據對應的客戶帳號對象,即:Session[Ticket] = AccountObject,在確認身份后在填寫AccountObject具體內容:帳號、RSA加密鑰匙對、DES加密矢量
完成上述步驟后,服務器將RSAPublicKey傳回給客戶端。
1.3 加密登錄口令及DES加密矢量
客戶端獲得RSAPulbicKey后,產生自己的DES加密矢量DESCipherVector(至少要8位及以上,該加密矢量用於以后的常規通信消息加密,因為其速度比RSA快)。接着,客戶端使用RSAPublicKey加密登錄帳號、口令及DESCipherVector,連同Ticket,發送到服務器並請求身份驗證。登錄API格式如下:
public void Login(string Ticket, string cipherLongID, string cipherPassword);
如果驗證成功,服務器將當前帳號信息、RSA鑰匙、DESCipherVector等保存到會話Session[Ticket]中。
2 WebService通信安全性
2.1 加密WebService API參數
身份確認后,在客戶端調用的WebService API中,必須包括參數Ticket,其它參數則均使用DESCipherVector加密。服務器端返回的消息也同樣處理。例如,提交一個修改email的函數定義為:
public void ModifyEmail(string Ticket, string cipherEmai);
2.2 客戶端解密消息
客戶端接收到服務器返回消息后,先做解密操作,如果成功則進入下步處理。否則拋出加密信息異常。
2.3 服務器端解密消息
服務器接收到客戶提交的API請求后,首先驗證Ticket的合法性,即查找Session中是否有該票據以驗證客戶身份。然后,解密調用參數。如果成功則進入下不操作,否則返回操作異常消息給客戶端。
需要指出,如果第三方截獲全部會話消息,並保留其Ticket,此時服務器端仍然認可這個第三方消息。但是,第三方不能瀏覽,也不能修改調用API的參數內容,此時解密參數時將拋出異常。
上面探討了一個基於加密的WebService訪問與通信安全方法,即使第三方獲取消息,不能查看原始內容,也不能修改內容,保證了WebService API的安全性。
本方案還是存在一個明顯的缺陷,即:如果直接修改調用參數內容,在客戶端或服務器端解密時不拋出異常,如何處理?如何保證解密時一定拋出異常?這個待以后研究后回答。