上面一期簡要介紹了一下思路,這一篇文章講一下實現。
接上文
二、架構
系統從總體上分為兩部分,一部為企業的EBS及介面系統,第二部分為第三方廠商自建系統。
在企業總部系統部分,又分為兩部分,一部分為WS介面系統,第二部分為原始EBS系統。
在EBS部分,又可以分為正式表和介面表兩部分。
整體需求在技術上分為兩類:
Ø 唯讀EBS
WS直接從EBS生產表或介面表中讀取資料,因為不涉及到寫入操作,所以只要清楚資料庫結構即可得到所需要的資料;
Ø 讀寫EBS(需要互動)
這部分工作比較複雜,需要對EBS進行寫入操作,因為EBS的複雜性,需要把內容寫入到介面表中,由標準請求來處理介面表到正式表的匯入。
在資料匯入到正式表的過程中,有可能發生驗證失敗的情況,這種情況下,標準請求一般會在介面表或其它地方記錄出錯的資訊,如果第三方需要這個資訊,可以調用介面表從而得出相應的結論。總之,第三方與EBS的互動可以靠兩種方式組合得出,但是互動的效率可能會相對稍慢,即中間有一定的延時。
所謂標準請求,是指EBS內建的一些功能,至於它都有哪些標準請求,需要查閱EBS的相關文檔,它們有的就是有,它們沒有的,誰也不能提供。
在技術架構方面,WebService介面部分採用Visual Studio 2008來開發,因為WebService與具體的程式語言無關,所以只要使用標準的介面規則,就可以被多個第三方廠商所使用。
三、WebService介面實現
WS伺服器採用Windows2008+IIS來實現,由WS來實現第三方廠商與EBS的溝通及互動,保證第三方廠商的系統(無論是在總部還是在海外IDC)都可以順利的與EBS進行通訊。在介面實現這一部分,將分多個部分進行說明:
Ø 安全通訊
在第三方與WS通訊的時候,需要考慮通訊的安全性,WS本身將採用HTTPS的方式來工作。
因為不能保證全部第三方系統都能採用域驗證的方式來使用,所以在資料轉送上,還需要考慮一些更通用的WS的驗證方式。
在每新增加一個第三方廠商的時候,系統會分配給他們一個密碼串(32位元組),這個密碼串是每個廠商(系統)唯一的,也不會在不同的廠商之間互相通報,每次資料發送,都會帶著這個密碼串一起發過來,這樣可以首先確定上傳資料的合法性,同理,資料下傳的時候也會採用此種方式。
Ø 靈活性
WS設計的原則應該是盡量把資料庫表進行封裝,使得第三方無須過多的瞭解EBS的表結構即可以正常工作,但是同時還要考慮WS的擴充性,所以不能做太多的介面函數,應該盡量採用Schema的方式來描述,每個Schema將與具體的業務及操作相對應,Schema的擴充相當靈活,可以隨著業務的發展和新的第三方廠商的介入不斷的完善及發展,形成一個標準的EBS介面Schema庫,並形成相應的說明,可以挑選合適的Schema來使用。
到此為止,我們只說明了實現的兩個方面,安全性和靈活性,在下一期中,我們將對其它幾個方面進行說明。
Ø 讀取資料
讀取資料使用專門的介面函數,並且只有一個函數,可以做幾次重載來實現不同的需要,更多的情況是靠schema參數來區分操作的類型,返回的類型為XML檔案,並且第三方會知道按何種方式來拆解此返回的XML。XML可以是單表,也可是多表的記錄集的形式,具體返回格式完全由Schema來指定;在返回之前,考慮傳輸的效率,需要對返回的資料進行壓縮,然後再位元組的形式來返回
² 函數原型
public byte[] GetData(string schemaName,string whereClause,string password) //取出指定條件的記錄集
² 參數
schemaName
指定的模式名稱,對於模式及模式的使用方式,在後面會有專門的描述
根據指定的模式,系統會找到相對應的表,返回所需要的欄位
whereClause
它是根據一個查詢條件來返回記錄,這樣可以實現很複雜的查詢功能,返回的記錄集遵循指定的Schema
password
由系統分配給第三方廠商(系統)的一個hash串,作為唯一的標識,伺服器端接收到訊息後,會檢查這個密碼串的合法性,如果系統中不存在這個串,則不能進行任何操作。
關於密碼串的具體說明和用法,在後面有專門的描述。
² 傳回值
傳回值一律為位元組數組,而不採用XML直接返回,這樣可以在傳輸之前做更多的處理,比如壓縮和加密,本次設計中暫不包括加密處理,壓縮採用標準的壓縮演算法。
第三方在收到位元組數組後,使用標準的壓縮演算法將其解開,還原成一個XML檔案
在第三方用戶端,會存在相應的Schema來解析這個XML,具體使用哪個Schema,由用戶端自己來把握,與伺服器端無關,資訊拆解後如何使用,也由用戶端自己把握。
如果操作失敗,返回的錯誤也會按位元組數組的形式來返回,所以用戶端接收後首先要檢查操作是否成功,如果確認沒有失敗,再去檢查具體的返回內容。
Ø 寫入函數
寫入動作是指由用戶端發起,向伺服器寫入相關的內容,在本系統中,寫入的內容與業務無關,全部抽象為技術層面來處理。
² 函數原型
public byte[] WriteData(string schemaName,byte[] content,string password)
² 參數
schemaName
與讀取函數的功能相似。
content
要寫入的內容,在用戶端產生,首先產生一個XML檔案,與schemaName相對應,產生XML後,在用戶端進行壓縮和加密等操作,產生一個二進位的位元組數組上傳 到伺服器。
password
與讀取函數功能相似。
² 傳回值
與讀取函數類似,返回位元組數組,用戶端先要對其進行解壓和解密方可使用,儘管很少量的內容返回壓縮後反而會更大,但是為了統一的管理方式,仍採用這種方式來工作。
Ø 資料傳遞
資料為雙向傳輸,即有些是從第三方系統寫入EBS,有些是從EBS讀取返回給第三方系統。
對於單向讀取(EBS->第三方),沒有資料一致性的風險,直接返回即可,完全通過Schema的添加和配置就可以實現資料安全有效控制。
但是對於另一個方面的傳輸(第三方->EBS),就存在著一個比較敏感的問題,因為EBS的資料結構非常複雜,很難完全掌握它的結構,所以這個方向的傳輸,一定要把握一個原則,就是只能寫到EBS的介面表中,不能直接寫入生產表。這部分內容會在Schema部分有更詳細的說明。
在下一期中,我們將來詳細的介紹一下系統的安全性。
四、安全體系
在上面的章節也提到了資料的安全及一些策略,在此將詳細的論述安全的資料轉送。
Ø SSL體系
這是一個網路層的解決方案,具體做法是在IIS上配置相應的SSL認證,從而實現一個SSL的網站,安全性憑證採用VeriSign,可以從中國的代理機構購買。
SSL的方式會增高系統的安全性,但是也會對效能有一點點的影向,不過不會成為系統的效能瓶頸。
另外還需要驗證是否所有的第三方廠商在寫程式的時候都支援這種SSL方式,因此這個體系作為一個可選件存在,可以隨時啟用,不影響整體的架構。
Ø 壓縮與加密
當資料在用戶端與伺服器通訊的時候,如果不採用SSL的方式,則資訊在internet上是可以被截獲並破解的,為瞭解決這個問題,需要對資料做一定的預先處理,然後再 進行傳輸。
壓縮是必選項,採用標準的ZIP壓縮演算法,用戶端採用何種工具進行壓縮和解密由用戶端自己把握,不提供專門的處理函數。
對於密碼編譯演算法,可以採用標準的密碼編譯演算法,也可以採用自己定義的簡單密碼編譯演算法,也可以暫時不考慮加密,只用壓縮來處理,本期暫不考慮密碼編譯演算法。
Ø 密碼串(識別碼)
系統會為每個第三方廠商(系統)分配一個唯一的識別碼,為了加強此識別碼的強度,採用32位元組長度的密碼串,此密碼串本身沒有任何含義,只作為唯一的標識,加大它的長度,即減少了被盜用的風險。
關於密碼串的分發,不考慮程式實現,只用手工處理即可,可以使用郵件的方式來發送。
為了驗證密碼串,需要伺服器端與用戶端都同時儲存這個密碼串,這樣才可以驗證。這裡的伺服器指的是WebService伺服器,而不是EBS伺服器,因為不方便在EBS中添加過多的定製化內容。
在伺服器端,密碼串的儲存可以直接使用XML檔案或一般檔案都可以,這個可以在具體實現的時候再決定,在檔案中僅需要簡單的儲存以下資訊:
² 密碼串
用於溝通的字串,32位元組長,手工產生,隨意產生,沒有規則,只要保證能正確下發到相關的第三方廠商手中即可。
² 廠商名稱
用於標識,系統中不使用此標識。
² 有效起始日期
大於此日期後,該密碼串才被認為是合法的,此欄位不可為空,可以靠很小的日期來處理特別情況。
² 有效結束日期
小於此日期,該密碼串才被認為是合法的,此欄位不可為空,可以靠很大的日期來認為是無限期的,以上兩個日期可以隨時調整,以更改密碼的可用性。
² 建立日期
此條記錄添加的日期。
² 建立人(字串描述)
是誰添加了這條記錄。
² 最後修改日期
² 最後修改人
在伺服器IIS啟動的時候,在Instance_Startup類型的函數中,加上特別的處理,把所有的密碼串全部讀出來,放入Global變數中(唯讀取密碼串一個欄位,其它均不讀入),在WebService的GetData/WriteData函數中,首選檢查傳入的密碼串參數是否是合法的,如果是合法的,再繼續後面的操作,如果是非法的,直接返回“非法使用”之類的錯誤。
驗證函式如下:
private bool ValidPassword(string password)
用戶端收到總部關於密碼的郵件後,所有的操作均必須帶著這個密碼,如果因為密碼填寫錯誤,會造成一系列的錯誤,需要第三方自己把握。
關於密碼變更:
密碼變更在伺服器上需要對原密碼的有效結束日期變更,並記錄更改人;
同時添加一條新的記錄,並確認結束日期合法;
最後把新的密碼下發給第三方廠商。
Ø 資料庫表ACL
原則上用戶端會按照約定的規則來讀取和寫入資料,但是為了防止惡意讀寫,在此專門設定ACL,控制哪些表可以讀寫,ACL檔案為標準的XML檔案,包括以下三個屬性:
² 表名(大寫)
² 是否可讀(BOOL型)
² 是否可寫(BOOL型)
同樣,在系統啟動的時候,會把這些資訊讀入到記憶體中備用。
Ø 私人資訊
同一張介面表中,可能會同時有多個廠商進行操作,這時要保證不同的廠商之間的操作不會互相影響,為此需要在相應的介面表中找一個合適的欄位,來儲存廠商的密碼串。
在後面的部分,我們將對Schema進行描述,這是資料通訊的基本單位。
五、XML Schema
為了實現更通用性的互動,Schema是最重要的一部分。
這裡的Schema是標準的模版xsd文檔,遵循所有的標準規格。
關於XML Schema的詳細內容,在此不做描述,可以從其官方網站上得到解釋。
在讀取資料和寫入資料的時候,都會用到Schema,Schema就是用來實現對原始表的一個映射。
在伺服器端(WebService伺服器)和用戶端都存在一份Schema列表,在伺服器上儲存全部的Schema,但是在用戶端,只儲存和自己業務相關的部分,不會儲存全部Schema。
Ø 資料讀取
Schema檔案用於資料的描述,但是和資料庫本身沒有任何依賴關係,現在需要根據這個Schema來得到一個SQL語句才可以去資料庫裡取資料。為了簡單快速的實現Schema與SQL語句的轉換,可以再寫一個專門的檔案,檔案名稱與Schema相同,副檔名為.select,表示是一個選擇資料的SQL語句,此檔案只存在於伺服器上,用戶端不知道此檔案的存在。在Instance_Startup的函數中,將所有相關的SQL全部一次性讀入到記憶體中,方便後期快速使用,當然如果有任何這種檔案的變化,都需要IIS的重新起動。
對於where條件,可以作為一個字串直接拼接在SQL後面,得到一個真正的SQL語句,SQL中沒有參數的概念,拼接完成的SQL,在資料庫中可以直接使用,為保證SQL的可用性,用戶端在寫where條件的時候一定要遵循一定的規則,包括and / or 之類的匹配關係,小括弧/單引號的使用等,一定要正確。
對於標準的XML的產生,有兩種方案:
如果Oracle10g支援XML SQL,可以直接產生符合xsd標準的XML檔案;
如果不支援,只能返回一個DataSet,再參考Schema的格式,手工產生一個XML檔案。
產生XML後,調用壓縮公用程式包對其進行相關的壓縮處理,產生位元組,直接返回。
如果使用過程中發生錯誤,則返回“查詢錯誤”之類的代碼,可以把相關的錯誤碼返回。
在讀取之前,需要判斷此表在ACL列表中是否可讀(如果不好判斷,可以跳過此步驟,因為SQL不是用戶端可以更改的)。
Ø 資料寫入
資料寫入的函數裡面有一個位元組數組,首先對其進行解壓及解密,產生一個XML檔案,此檔案與Schema配合,讀入系統成為一個標準的DataSet,此時可以利用現有的技術直接把該內容寫入到資料庫中,在寫入之前,一定要去ACL中檢查一下,此表是否可以寫入。
六、EBS端相關操作
所有的寫入操作均寫入EBS的介面表中,不會直接寫入正式表,因此寫入介面表中後,需要調用EBS的標準請求來把介面表寫入正式表。
關於介面表,不同的模組有不同的介面表,並且有不同的操作方式,有不同的請求來實現,所以需要根據實際的介面情況,考慮EBS的介面表及標準請求,並研究標準請求返回的錯誤資訊及含義,還有就是錯誤返回的儲存位置,有些直接回寫入介面表,有些會寫入標準的錯誤記錄檔表中,具體在操作的時候再確定。
七、總結
以上方式已經在我公司得到真正的應用,並已經為多個業務系統服役,使用效果良好,希望大家參考後能有所協助。