" v% n% C# J* H; n, M" t: w
前面hawkfly提到的在多层编程中,服务器端安全性验证的问题
7 c3 Z, s& r# b; v' y4 J; A4 @5 v在以socket方式实现MIDAS时尤为明显,DCOM/CORBA都有现成的
安全管理功能,而socket方式在这方面比较薄弱,没有现成的解决方案
2 k0 y Z4 e3 a$ v现就我以前对MIDAS编程的理解,做一个简要的介绍,
8 `# D3 w7 X0 p V# t以后有时间精力再详细举例说明
% R, Q; r8 A; S3 @: k# d r
win2k中dcom的安全级别有7种,其中
# `0 K3 g* m" k1 w) F最低的“无”安全检查暂且不论
默认的“身份验证”服务方式几句话也说不清,
先放到一边,看看剩下的5种
1.连接,仅对初始连接进行安全检查
1 l8 A6 \3 \3 d ?3 Q$ A! f
因为tcp/ip是稳固的连接,因此每个连接,也就是每个RemoteDataModule
7 h" D, g& P3 r6 R实例检测一次即可,实现方法很多,这里简要介绍一种最简单的
可以在服务器端的TypeLibrary里面为你的服务器接口增加若干个方法,如
interface ILoginServer: IAppServer
2 A i( e6 e" k8 r+ |' V T% q{
[
, L9 S" c- g) ~0 aid(0x00000001)
7 X& J! I! n0 w1 J]
2 r+ ~$ ~& N4 c$ n! IHRESULT _stdcall Login( void );
[
id(0x00000002)
w7 }, u6 f2 [' m2 M- x: \: W" W! N+ {]
HRESULT _stdcall Logout( void );
' C0 |7 \! m: r1 Y5 ^7 c- V1 _* Z};
3 w0 W; l% I4 G9 n+ r, a! e在方法中实现你的客户身份校验,而在校验之前,通过把RDM上所有的TDataSetProvider
! k) y L" l! H的Exported属性关掉即可让客户端无法看到服务器端的provider
+ H, k$ o& c( M4 H* v# f7 B' l+ }9 t因为客户端实际上是在连接服务器成功后通过服务器之IAppServer接口访问
所有的Provider,如IAppServer::AS_GetProviderNames可以取得
服务器端所有exported的IProvider接口名称,而所有数据的取得、修改
都是通过相应的ProviderName来指定的,如
) k& ?; q& D& m7 N# n8 x- `0 t( Vvirtual HRESULT __safecall AS_GetRecords(const WideString: ProviderName, in
* j* Z' k3 |, Z9 i0 _. s, Gt Count, int &RecsOut, int Options, const WideString: CommandText, OleVarian
t &
arams, OleVariant: &OwnerData, OleVariant &GetRecords_result) = 0 ;
取得数据方法的第一个参数就是你需要操作的数据集名称……
如果你把服务器RDM上所有的TDataSetProvider::Exported关掉,
! r1 `' `3 v" E( [8 _( H2 s# D则客户端看不到任何Provider,也无法通过其ProviderName取得数据
* o; a; Y: W, o) P2 ]! \例如我在服务器端的RDM类中加入
/ N: Z$ C6 {3 ^+ A/ n+ |4 Rclass TLoginServer : public TCRemoteDataModule
/ o/ ~8 J6 E2 _( P{
! m, V* P7 d4 H# w8 K2 B: d1 W6 c% N...
2 ?0 u- _0 g% h) J0 a' l% `private: // User declarations
bool FLogin;
' W" w9 _( V" gvoid __fastcall SetLogin(bool value);
) T, t6 W: ^- S. H& d4 h: ^! a* Tbool __fastcall IsLogin(OleVariant &OwnerData);
! G& m5 s! u9 h% ]5 N% ^...
__published:
__property bool Login = { read = FLogin, write = SetLogin };
};
在RDM实现类中
! A9 i1 ~1 H- n, X: x: v/ fclass ATL_NO_VTABLE TLoginServerImpl: 。。。
{
// ILoginServer
/ m* j" v* k B8 X& ~protected:
% X( x1 N2 d9 O* j6 T2 qSTDMETHOD(Login());
& c7 m+ R' y7 \' E TSTDMETHOD(Logout());
) L5 G4 }, c4 [) c};
然后简单实现之
__fastcall TLoginServer::TLoginServer(TComponent* Owner)
: TCRemoteDataModule(Owner), FLogin(false)
" t! [7 L5 r+ Z u' ^( F* J{
# k9 [) r: n8 o8 T$ A}
. l& {( p* F2 t' y0 u, V, C//---------------------------------------------------------------------------
void __fastcall TLoginServer::SetLogin(bool value)
{
if(FLogin != value)
- w3 }' B z* b7 B{
FLogin = value;
dspAnimals->Exported = FLogin;
}
; M0 P( E- b7 m% X& F}
//---------------------------------------------------------------------------
( [. T) V3 |. I' ]STDMETHODIMP TLoginServerImpl:
ogin()
{
m_DataModule->Login = true;
+ h7 R8 s) u5 }: A: R7 c6 F* k$ Hreturn S_OK;
}
7 {/ {" f& r$ C% [: T" b* {( F) |//---------------------------------------------------------------------------
1 F& S* _. i% w5 d% r0 aSTDMETHODIMP TLoginServerImpl:
ogout()
{
m_DataModule->Login = false;
return S_FALSE;
4 k" i7 a- y7 O. g K}
//---------------------------------------------------------------------------
9 d: e0 e& I; kbool __fastcall TLoginServer::IsLogin(OleVariant &OwnerData)
{
return FLogin;
}
2 _. N. ^5 y# v' m% p1 Reasy
这样除非你的客户端成功调用Login方法,否则他是无法使用
dspAnimals这个数据集Provider的,成功调用后手工打开的数据集使用完全相同
4 K) ^0 ]/ J* I+ x$ Q7 p) B
比如客户端可以用如下代码
IDispatch *dispAppServer = (IDispatch*)(DM->Connection->AppServer);
- Z3 p" l$ |& ^+ nILoginServerDisp dispLoginServer = (ILoginServer *)dispAppServer;
dispLoginServer.Login();
' M+ Y; c1 m; g# eDM->cdsAnimals->Open();
实现注册,并且打开相应数据集……
. A; ~$ K5 W( }. X8 }+ j/ L- y4 t# [
因为大多数的三层程序对安全性要求并不高,因此这样的安全检测对
绝大多数程序应该足以……
| 欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) | Powered by Discuz! X2.5 |