[本站首页] [管理页面] [写新日志] [退出]

朝为田舍郎,暮登天子堂,将相本无种,男儿当自强。
首页(178) Hibernate(10) JAVA(19) Web(15) Struts(7) 口水(9) Ides(18) 其它(51) AJAX(6) database(29) 
Blog信息

blog名称:四裤全输的小窝~~
日志总数:178
评论数量:699
留言数量:198
访问次数:1156941
建立时间:2005年10月29日

Blog内搜索



日志更新

谷歌地图定位偏移解决方法
【转】利用Windows内置的命令作端口
WIN2003服务器安全加固方案
[转]sql server 日期比较、日
MediaCoder 一般参数设置
[转]VMware中创建共享磁盘阵列的方
缓解vss共享文件夹的安全隐患问题(转)
Delphi 中调用JavaScript
微软的官方方法:延长Windows Se
cxGrid 过滤 排序后 取选中记录的

最新评论

回复:谷歌地图定位偏移解决方法
回复:谷歌地图定位偏移解决方法
回复:WIN2003服务器安全加固方案
回复:cxGrid 过滤 排序后 取选中
回复:TreeView 父节点 子节点 
回复:[转]Oracle Instead
回复:DWR 官方下载地址
ugg  boots
回复:cxGrid 过滤 排序后 取选中
回复:DWR 官方下载地址

友情链接

biglin's Blog
NoisyRam's Blog
Stone's Blog
Kevin 的小家
『知』治通鉴

留言板




[Ides]非匿名方式访问远程的com+
文章收藏,  网上资源,  软件技术,  电脑与网络 四裤全输 发表于 2007/10/9 11:54:13

转自:http://blog.csdn.net/looyo/archive/2007/07/27/1711546.aspxwindwos的安全机制规定:windows接收远程的com+调用的时候,会验证这个调用的权限。如果权限不够就出现经典的“拒绝访问”错误。 解决这个问题已知访问方式有: 1、匿名访问;在应用服务器(简称AP)启用guest,并且设置guest具有激活和访问COM+的权限。这条路是可行,不过安全性不能得到保证。 2、客户端电脑的登录用户和密码和AP上的一个用户一致,并且这个用户在AP上也具有相应的访问COM+的权限。这种方式要比第一种好一些,但是哪个单位的IT系统会是这种样子呢。肯定是每台机器都有自己的帐户密码。这个方式也不好。注:这种方式在不需要发布客户端软件到诺干多的机器上的时候也是可行的,比如访问COM+ 的是webServer. 3、在域管理的网络环境中,同样可以实现,但是有个问题,如果您的客户不愿意改造成域环境呢。所以这种方法也是有局限性的。 最后,我想到如果远程访问COM+的时候能够显式的给定用于AP验证权限的用户名和密码不是就可以解决这个问题了吗?事实上这个方式是可行的。不过在delphi7中还没有现成的函数可以达到这个目的。 comobj.pas 中有个函数 function CreateRemoteComObject(const MachineName: WideString;  const ClassID: TGUID): IUnknown; 这个是用来创建远程的com+接口的。我要改造的主要是这个函数。   function CoCreateInstanceEx(const clsid: TCLSID; unkOuter: IUnknown; dwClsCtx: Longint; ServerInfo: PCoServerInfo; dwCount: Longint; rgmqResults: PMultiQIArray): HResult; stdcall; 这个函数可以用来创建远程的com+ ServerInfo 用来存储远程的服务器信息,包括访问和激活com+服务的帐户和密码。 我们来分析一下PCoServerInfo;  PCoServerInfo = ^TCoServerInfo;  _COSERVERINFO = record    dwReserved1: Longint;    pwszName: LPWSTR;    pAuthInfo: Pointer;    dwReserved2: Longint;  end;     pUnShort=^Word;    pCoAuthIdentity=^_CoAuthIdentity;    _CoAuthIdentity=record        user:pUnShort;        UserLength:ULONG;        Domain:pUnShort;        DomainLength:Ulong;        password:pUnShort;        PasswordLength:ulong;        Flags:ulong;    end;    _CoAuthInfo=record        dwAuthnSvc:DWORD;        dwAuthzSvc:DWORD;        pwszServerPrincName:WideString;        dwAuthnLevel:Dword;        dwImpersonationLevel:dword;        pAuthIdentityData:pCoAuthIdentity;        dwCapabilities:DWORD;    end;    TSocInfo=class(Tobject)    public        fcid:_CoAuthIdentity;        fcai:_CoAuthInfo;        ServerInfo: TCoServerInfo;    end; 我们在CreateRemoteComObject中调用CoCreateInstanceEx的时候,首先给ServerInfo赋值如下 function CreateRemoteComObjectwh(const MachineName: WideString; const ClassID: TGUID): IUnknown;const  LocalFlags =CLSCTX_LOCAL_SERVER or CLSCTX_REMOTE_SERVER or CLSCTX_INPROC_SERVER;  RemoteFlags = CLSCTX_REMOTE_SERVER;var    MQI: TMultiQI;    ServerInfo: TCoServerInfo;    IID_IUnknown: TGuid;    Flags, Size: DWORD;    LocalMachine: array [0..MAX_COMPUTERNAME_LENGTH] of char;  ////  add by wanghui 2007-07-24    Fcai:_CoAuthInfo;    Fcid:_CoAuthIdentity;     wUser,wDomain,wPsw:WideString;    iiu:idispatch;    fr:HRESULT;begin  if (GetObjectContext = nil)  then  begin        if @CoCreateInstanceEx =nil then            raise Exception.CreateRes(@SDCOMNotInstalled);     wUser:=getAppUserid();//用户名    wDomain:=getappserver();//远程计算机名    wPsw:=getAppPassword();//密码     FillMemory(@Fcai,sizeof(Fcai),0);    FillMemory(@FCid,sizeof(FCid),0);     with fcid do begin        user:=pUnshort(@wUser[1]);        UserLength:=length(wUser);        Domain:=pUnshort(@wDomain[1]);        DomainLength:=length(wDomain);        password:=pUnshort(@wPsw[1]);        PasswordLength:=length(wPsw);        Flags:=2;    end;     with fcai do begin        dwAuthnSvc:=10;//winNt默认的鉴证服务   RPC_C_AUTHN_WINNT        dwAuthzSvc:=$FFFFFF;//0;            //RPC_C_AUTHZ_NONE        //pwszServerPrincName:=pwidechar(wDomain);        dwAuthnLevel:=3;//0;        dwImpersonationLevel:=3;//必须设置成模拟        pAuthIdentityData:=@fcid;        dwCapabilities:=$0;//$0800;    end;    FillMemory(@ServerInfo, sizeof(ServerInfo), 0);    ServerInfo.pwszName := PWideChar(wDomain);    ServerInfo.dwReserved1:=0;    ServerInfo.pAuthInfo:=@fcai;     IID_IUnknown := IUnknown;    MQI.IID := @IID_IUnknown;    MQI.itf := nil;    MQI.hr := 0;     if Length(MachineName) > 0 then    begin        Size := Sizeof(LocalMachine);  // Win95 is hypersensitive to size        if GetComputerName(LocalMachine, Size) and  (AnsiCompareText(LocalMachine, MachineName) = 0) then          Flags := LocalFlags        else          Flags := RemoteFlags;    end else Flags := LocalFlags;    OleCheck(CoCreateInstanceEx(ClassID, nil, CLSCTX_REMOTE_SERVER, @(ServerInfo), 1, @MQI));    OleCheck(MQI.HR);    Result := MQI.itf;  end   else  begin        GetObjectContext.CreateInstance(ClassID, IUnknown, Result);  end;end; 以上代码 确保获取远程的com+的接口,接口类型为Iunkown 但是要访问其中的方法还需要用下面的函数来设置远程com本地引用的访问权限。  with fcai do        CoSetProxyBlanket(iu,dwAuthnSvc,dwAuthzSvc,pwidechar(pAuthIdentityData^.Domain),            dwAuthnLevel,dwImpersonationLevel,pAuthIdentityData,dwCapabilities); 将这个函数封装后得到一个新函数 function SetProxyBlanket(iu:IUnknown):boolean;var    Fcai:_CoAuthInfo;    Fcid:_CoAuthIdentity;    wUser,wDomain,wPsw:WideString;    iiu:idispatch;     si:Tsocinfo;begin    wUser:=getAppUserid();//用户名    wDomain:=getappserver();//远程计算机名    wPsw:=getAppPassword();//密码   if wDomain='127.0.0.1' then exit;    FillMemory(@Fcai,sizeof(Fcai),0);    FillMemory(@FCid,sizeof(FCid),0);    // FillMemory(@FSvInfo,sizeof(FSvInfo),0);    with fcid do begin        user:=pUnshort(@wUser[1]);        UserLength:=length(wUser);        Domain:=pUnshort(@wDomain[1]);        DomainLength:=length(wDomain);        password:=pUnshort(@wPsw[1]);        PasswordLength:=length(wPsw);        Flags:=2;      //SEC_WINNT_AUTH_IDENTITY_UNICODE    end;    //以上填充_CoAuthIdentity结构   with fcai do begin        dwAuthnSvc:=10;//winNt默认的鉴证服务   RPC_C_AUTHN_WINNT        dwAuthzSvc:=$FFFFFF;//0;            //RPC_C_AUTHZ_NONE        //pwszServerPrincName:=pwidechar(wDomain);        dwAuthnLevel:=3;//0;        dwImpersonationLevel:=3;//必须设置成模拟        pAuthIdentityData:=@fcid;        dwCapabilities:=$0;//$0800;    end;       with fcai do        CoSetProxyBlanket(iu,dwAuthnSvc,dwAuthzSvc,pwidechar(pAuthIdentityData^.Domain),            dwAuthnLevel,dwImpersonationLevel,pAuthIdentityData,dwCapabilities);end; 最后我们改造delphi自动生成的*_TLB.pas 中的函数CreateRemote 如下 class function Comymenu.CreateRemote(const MachineName: string): Imymenu;var  iu:IUnknown;begin    iu:=CreateRemoteComObjectwh(MachineName, CLASS_mymenu);    SetProxyBlanket(iu);    result:=iu as Imymenu;    SetProxyBlanket(IUnknown(result));end; 参考了一些资料:MSDN,《windows安全性编程》。 软件环境:   client  winXP SP2 AP: win2003 sp1


阅读全文(5165) | 回复(0) | 编辑 | 精华


发表评论:
昵称:
密码:
主页:
标题:
验证码:  (不区分大小写,请仔细填写,输错需重写评论内容!)
站点首页 | 联系我们 | 博客注册 | 博客登陆

Sponsored By W3CHINA
W3CHINA Blog 0.8 Processed in 0.285 second(s), page refreshed 144808682 times.
《全国人大常委会关于维护互联网安全的决定》  《计算机信息网络国际联网安全保护管理办法》
苏ICP备05006046号