增強(qiáng)MIDAS的安全性
大家都知道,使用RemoteDataModule最令人頭疼的就是安全性問(wèn)題。
主要體現(xiàn)在:
1、遠(yuǎn)端只要知道應(yīng)用服務(wù)器的端口號(hào)即可訪問(wèn)到應(yīng)用服務(wù)器,而一旦訪問(wèn)到應(yīng)用服務(wù)器,TClientDataSet即可獲得ProviderNames列表。(觀點(diǎn):不讓他輕易得到ProviderNames列表。)
2、一旦知道了ProviderNames列表,這就相當(dāng)于將數(shù)據(jù)庫(kù)暴露在外了。
例如:客戶端可以通過(guò)SQL語(yǔ)句來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作了。(觀點(diǎn):我們的應(yīng)用服務(wù)器根部不接受SQL語(yǔ)句。)
因?yàn)榭吹酱蠹掖祟?lèi)貼多如牛毛,又沒(méi)有什么更好的解決方法,因此我發(fā)表一下我的拙見(jiàn)。
我對(duì)IAppServer接口進(jìn)行了進(jìn)一步的擴(kuò)展,增強(qiáng)了RemoteDataModule的安全性。主要體現(xiàn)在:
1、客戶端偵測(cè)到應(yīng)用服務(wù)器的端口號(hào)可以建立與應(yīng)用服務(wù)器的連接,但必須提供由TClientDataSet提供一GUID作為密碼方能在設(shè)計(jì)階段獲得ProviderNames列表。此功能使得系統(tǒng)外部人員無(wú)法在設(shè)計(jì)階段直接在TClientDataSet的ProviderName中直接獲得應(yīng)用服務(wù)器的TProvider實(shí)例。如果想通過(guò)IAppServer來(lái)獲取ProviderNames列表則必須提供這一特定的GUID作為密碼。
IAppServer的AS_GetProviderNames原形為
function AS_GetProviderNames: OleVariant; safecall;
擴(kuò)展后的函數(shù)為
function AS_GetProviderNames(Password:WideString): OleVariant; safecall;
系統(tǒng)外部人員能夠訪問(wèn)TRemoteDataModule的Provider的方法就是猜測(cè)(或者成為蒙)出可能有的ProviderName直接賦值給TClientDataSet的ProviderName屬性。當(dāng)然這是十分困難的(只要你不是直接將datasetProvider1作為T(mén)datasetProvider的名稱(chēng))。
2、雖然惡意者可能通過(guò)其他方法(包括猜測(cè)、窮舉)來(lái)獲取到一個(gè)具有較高權(quán)限的TProvider,但是此步的安全特性完全將其擋在了門(mén)外。
TClientDataSet必須提供加密后的CommandText串才能得到應(yīng)用服務(wù)的正確相應(yīng)。因?yàn)檫@里的加密對(duì)象是SQL語(yǔ)句(一個(gè)字符串),所以可以使用n多種加密方法。如果應(yīng)用服務(wù)器解密出的串為非法SQL串,會(huì)向客戶端返回SQL語(yǔ)法錯(cuò)誤信息。
而我在處理時(shí)并沒(méi)有對(duì)SQL進(jìn)行真正的加密,而是在TClientDataSet的CommandText中包含了一特定的字符串作為鑰匙,而如果服務(wù)器得到請(qǐng)求后在CommandText中沒(méi)有找到這一鑰匙則返回“Missiong SQL property”異常。如果服務(wù)器得到了這一鑰匙,則將這一鑰匙從CommandText串中移除后交給TProvider進(jìn)行處理。
實(shí)現(xiàn):
聽(tīng)上去好像很玄,但實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單:
我這里簡(jiǎn)單說(shuō)說(shuō)對(duì)SQL串的加密方法:
打開(kāi)Provider單元,找到TDataSetProvider的SetCommandText方法。
你應(yīng)該明白了吧。。。
如果你比我還菜,你就這樣寫(xiě):
var commandt:string;
begin
if CommandText=\’\’ then Exit;
if Copy(Commandtext,1,8)<>\’minercxy\’ then Exit;
commandt:=Copy(CommandText,9,length(CommandText)-8);
if not(poAllowCommandTet in Options) then
DatabaseError(SCannotChangeCommandText);
CheckDataSet;
IProviderSupport(DataSet).PSSetCommandText(CommandT);
end;
發(fā)布問(wèn)題,編譯Provider單元并將Provider.dcu文件和并入應(yīng)用服務(wù)器目錄中,編譯應(yīng)用服務(wù)器。這樣Tclientdataset必須提供\’minercxy\’+\’select * from ...\’ 這樣的命令才能被服務(wù)器承認(rèn)?! ∥野裓’minercxy\’暫且稱(chēng)為鑰匙,鑰匙可以自己進(jìn)行隨意設(shè)置,位數(shù)也可隨意長(zhǎng)度。當(dāng)然鑰匙的隨機(jī)性越大安全性就越強(qiáng)了。
大家都知道,使用RemoteDataModule最令人頭疼的就是安全性問(wèn)題。
主要體現(xiàn)在:
1、遠(yuǎn)端只要知道應(yīng)用服務(wù)器的端口號(hào)即可訪問(wèn)到應(yīng)用服務(wù)器,而一旦訪問(wèn)到應(yīng)用服務(wù)器,TClientDataSet即可獲得ProviderNames列表。(觀點(diǎn):不讓他輕易得到ProviderNames列表。)
2、一旦知道了ProviderNames列表,這就相當(dāng)于將數(shù)據(jù)庫(kù)暴露在外了。
例如:客戶端可以通過(guò)SQL語(yǔ)句來(lái)對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作了。(觀點(diǎn):我們的應(yīng)用服務(wù)器根部不接受SQL語(yǔ)句。)
因?yàn)榭吹酱蠹掖祟?lèi)貼多如牛毛,又沒(méi)有什么更好的解決方法,因此我發(fā)表一下我的拙見(jiàn)。
我對(duì)IAppServer接口進(jìn)行了進(jìn)一步的擴(kuò)展,增強(qiáng)了RemoteDataModule的安全性。主要體現(xiàn)在:
1、客戶端偵測(cè)到應(yīng)用服務(wù)器的端口號(hào)可以建立與應(yīng)用服務(wù)器的連接,但必須提供由TClientDataSet提供一GUID作為密碼方能在設(shè)計(jì)階段獲得ProviderNames列表。此功能使得系統(tǒng)外部人員無(wú)法在設(shè)計(jì)階段直接在TClientDataSet的ProviderName中直接獲得應(yīng)用服務(wù)器的TProvider實(shí)例。如果想通過(guò)IAppServer來(lái)獲取ProviderNames列表則必須提供這一特定的GUID作為密碼。
IAppServer的AS_GetProviderNames原形為
function AS_GetProviderNames: OleVariant; safecall;
擴(kuò)展后的函數(shù)為
function AS_GetProviderNames(Password:WideString): OleVariant; safecall;
系統(tǒng)外部人員能夠訪問(wèn)TRemoteDataModule的Provider的方法就是猜測(cè)(或者成為蒙)出可能有的ProviderName直接賦值給TClientDataSet的ProviderName屬性。當(dāng)然這是十分困難的(只要你不是直接將datasetProvider1作為T(mén)datasetProvider的名稱(chēng))。
2、雖然惡意者可能通過(guò)其他方法(包括猜測(cè)、窮舉)來(lái)獲取到一個(gè)具有較高權(quán)限的TProvider,但是此步的安全特性完全將其擋在了門(mén)外。
TClientDataSet必須提供加密后的CommandText串才能得到應(yīng)用服務(wù)的正確相應(yīng)。因?yàn)檫@里的加密對(duì)象是SQL語(yǔ)句(一個(gè)字符串),所以可以使用n多種加密方法。如果應(yīng)用服務(wù)器解密出的串為非法SQL串,會(huì)向客戶端返回SQL語(yǔ)法錯(cuò)誤信息。
而我在處理時(shí)并沒(méi)有對(duì)SQL進(jìn)行真正的加密,而是在TClientDataSet的CommandText中包含了一特定的字符串作為鑰匙,而如果服務(wù)器得到請(qǐng)求后在CommandText中沒(méi)有找到這一鑰匙則返回“Missiong SQL property”異常。如果服務(wù)器得到了這一鑰匙,則將這一鑰匙從CommandText串中移除后交給TProvider進(jìn)行處理。
實(shí)現(xiàn):
聽(tīng)上去好像很玄,但實(shí)現(xiàn)起來(lái)比較簡(jiǎn)單:
我這里簡(jiǎn)單說(shuō)說(shuō)對(duì)SQL串的加密方法:
打開(kāi)Provider單元,找到TDataSetProvider的SetCommandText方法。
你應(yīng)該明白了吧。。。
如果你比我還菜,你就這樣寫(xiě):
var commandt:string;
begin
if CommandText=\’\’ then Exit;
if Copy(Commandtext,1,8)<>\’minercxy\’ then Exit;
commandt:=Copy(CommandText,9,length(CommandText)-8);
if not(poAllowCommandTet in Options) then
DatabaseError(SCannotChangeCommandText);
CheckDataSet;
IProviderSupport(DataSet).PSSetCommandText(CommandT);
end;
發(fā)布問(wèn)題,編譯Provider單元并將Provider.dcu文件和并入應(yīng)用服務(wù)器目錄中,編譯應(yīng)用服務(wù)器。這樣Tclientdataset必須提供\’minercxy\’+\’select * from ...\’ 這樣的命令才能被服務(wù)器承認(rèn)?! ∥野裓’minercxy\’暫且稱(chēng)為鑰匙,鑰匙可以自己進(jìn)行隨意設(shè)置,位數(shù)也可隨意長(zhǎng)度。當(dāng)然鑰匙的隨機(jī)性越大安全性就越強(qiáng)了。