客户端如何delphi编程以远程用户身份访问win2003服务器的com+服务

作者&投稿:朱静 (若有异议请与网页底部的电邮联系)
这篇文章将会说明如何以远程工作站上的用户身份激活com+对象,并以此用户身份访问Interface。
1、 Delphi默认com+对象的远程激活
Delph中远程com+对象激活一般通过TdispatchConnection及其子类来实现,实际代码中多用TDCOMConnection或TsocketConnectoion这两个组件,TDCOMConnection组件最终调用CoCreateInstanceEx创建com+对象。CoCreateInstanceEx (const clsid: TCLSID; unkOuter: IUnknown; dwClsCtx: Longint; ServerInfo:PCoServerInfo;dwCount: Longint; rgmqResults: PMultiQIArray): HResult。

TDCOMConnection在调用CoCreateInstanceEx时为pCoServerInfo参数中的pAuthInfo传递了Null值,因此TdcomConnection在创建Com对象时使用的是本地计算机登录者的用户令牌。假若A计算机上的登录用户Auser使用TDCOMConnection类连接远程计算机B上的com+对象,则B计算机会使用Auser的用户名/密码在B计算机上建立登录会话并最终创建com+对象。但是一台windows工作站上的本地用户只能在本地登录而无法在别的计算机上登录,因此A计算机上的Auser就无法在B工作站上建立登录会话,当然也就无法创建com+对象,此时远程工作站B会尝试用Guest帐户建立会话并使用该账户激活com+对象。在这种情况下,如果B工作站上的Guest账户没有启用或Guest没有激活com+对象的权限,你就会看见令人头晕的提示“拒绝访问”。看到这里你是不对现在网上最“流行”的dcom配置方法有所悟了呢。那个方法就是允许everyone访问、激活com对象、并且将“默认身份验证级别”设置成无。这种方法能够使你的com应用可以“用了”,但是,它可以上“任何人”访问。而且这种设置你将无法利用com+基于角色的安全访问控制功能。
2、怎样不用GUEST账户激活
这个问题的实际上应该是:怎样用远程工作站上的用户激活远程com对象。解决这个问题其实很简单:只要你在调用CoCreateInstanceEx时为它指定远程工作站上的用户名和密码,只要用户名/密码通过远程计算机的验证,并且该用户被授予了“远程激活”com+对象的权限,那么远程工作站会用该用户身份激活com+对象。看一下代码:
var

mts:IMTSXjpimsDB;

ov:Variant;

i:integer;

cai:_CoAuthInfo;

cid:_CoAuthIdentity;

csi:COSERVERINFO;

mqi:MULTI_QI;

iid_unk:TGUID;

idsp:IDispatch;

wUser,wDomain,wPsw:WideString;

begin

wUser:=eduser.text;//用户名

wDomain:=edSvr.Text;//远程计算机名

wPsw:=edPsw.Text;//密码

cid.user:=pUnshort(@wUser[1]);

cid.UserLength:=length(wUser);

cid.Domain:=pUnshort(@wDomain[1]);

cid.DomainLength:=length(wDomain);

cid.password:=pUnshort(@wPsw[1]);

cid.PasswordLength:=length(wPsw);

cid.Flags:=2;

//以上填充_CoAuthIdentity结构

cai.dwAuthnSvc:=10;//winNt默认的鉴证服务

cai.dwAuthzSvc:=0;

cai.pwszServerPrincName:=wDomain;

cai.dwAuthnLevel:=0;

cai.dwImpersonationLevel:=3;//必须设置成模拟

cai.pAuthIdentityData:=@cid;

cai.dwCapabilities:=$0800;

//以上填充_CoAuthInfo结构
FillChar(csi, sizeof(csi), 0);

csi.dwReserved1:=0;

csi.pwszName:=pwidechar(wdomain);

csi.pAuthInfo:=@cai;

//以上填充COSERVERINFO结构

iid_unk:=IUnknown;

mqi.IID:=@iid_unk;mqi.Itf:=nil;mqi.hr:=0;

Screen.Cursor:=crHourGlass; olecheck(CoCreateInstanceEx(CLASS_MTSXjpimsDB,nil,CLSCTX_REMOTE_SERVER,@csi,1,@mqi));

这段代码中除了最后实际调用CoCreateInstanceEx外,前面的代码都是设置参数。这些参数的含义请大家参考msdn,除了用户名、主机名、密码外,只有一个重要要部分要说明:cai.dwImpersonationLevel必须设置成允许模拟(值为3),否则远程计算机将无法按提供的用户/密码建议网络会话。
3、不修改现有代码,可以实现用远程用户身份激活吗?
当然可以,我扩展了TDcomConnection类,为其加入了用户名和密码,并修改其默认的DoConnect方法,使其在调用CoCreateInstanceEx时用指定的用户名和密码填充参数。代码如下:
unit SecDComConnection;

interface

uses

windows,SysUtils, Classes,ActiveX, DB, DBClient, MConnect,comobj,Midas;

type

{typedef struct _SEC_WINNT_AUTH_IDENTITY

unsigned short __RPC_FAR* User;

unsigned long UserLength;

unsigned short __RPC_FAR* Domain;

unsigned long DomainLength;

unsigned short __RPC_FAR* Password;

unsigned long PasswordLength;

unsigned long Flags;

SEC_WINNT_AUTH_IDENTITY, *PSEC_WINNT_AUTH_IDENTITY;

}

{typedef struct _COAUTHIDENTITY

USHORT * User;

ULONG UserLength;

USHORT * Domain;

ULONG DomainLength;

USHORT * Password;

ULONG PasswordLength;

ULONG Flags;

COAUTHIDENTITY;}

{#define RPC_C_AUTHN_NONE 0

#define RPC_C_AUTHN_DCE_PRIVATE 1

#define RPC_C_AUTHN_DCE_PUBLIC 2

#define RPC_C_AUTHN_DEC_PUBLIC 4

#define RPC_C_AUTHN_GSS_NEGOTIATE 9

#define RPC_C_AUTHN_WINNT 10

#define RPC_C_AUTHN_GSS_SCHANNEL 14

#define RPC_C_AUTHN_GSS_KERBEROS 16

#define RPC_C_AUTHN_MSN 17

#define RPC_C_AUTHN_DPA 18

#define RPC_C_AUTHN_MQ 100

#define RPC_C_AUTHN_DEFAULT 0xFFFFFFFFL

}

{#define RPC_C_AUTHZ_NONE 0

#define RPC_C_AUTHZ_NAME 1

#define RPC_C_AUTHZ_DCE 2

#define RPC_C_AUTHZ_DEFAULT 0xFFFFFFFF }

{

#define RPC_C_AUTHN_LEVEL_DEFAULT 0

#define RPC_C_AUTHN_LEVEL_NONE 1

#define RPC_C_AUTHN_LEVEL_CONNECT 2

#define RPC_C_AUTHN_LEVEL_CALL 3

#define RPC_C_AUTHN_LEVEL_PKT 4

#define RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5

#define RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6 }

{SEC_WINNT_AUTH_IDENTITY_UNICODE=2 }

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;

TSecDComConnection = class(TDCOMConnection)

private

FCai:_CoAuthInfo;

FCid:_CoAuthIdentity;

FSvInfo:COSERVERINFO;

FUser:WideString;

FPassWord:WideString;

procedure SetPassword(const Value: wideString);

procedure SetUser(const Value: wideString);

procedure SetSvInfo(const Value: COSERVERINFO);

protected

procedure DoConnect; override;

public

property SvInfo:COSERVERINFO read FSvInfo write SetSvInfo;

constructor Create(AOwner: TComponent); override;

procedure MySetBlanket(itf:IUnknown;const vCai:_CoAuthInfo);

function GetServer: IAppServer; override;

published

property User:wideString read FUser write SetUser;

Property Password:wideString read FPassword write SetPassword;

end;

procedure Register;

implementation

constructor TSecDCOMConnection.Create(AOwner: TComponent);

begin

inherited Create(AOwner);

FillMemory(@Fcai,sizeof(Fcai),0);

FillMemory(@FCid,sizeof(FCid),0);

FillMemory(@FSvInfo,sizeof(FSvInfo),0);

with FCai do begin

dwAuthnSvc:=10;//RPC_C_AUTHN_WINNT

dwAuthzSvc:=0;// RPC_C_AUTHZ_NONE

dwAuthnLevel:=0;//RPC_C_AUTHN_LEVEL_DEFAULT

dwImpersonationLevel:=3;

pAuthIdentityData:=@fcid;

dwCapabilities:=$0800;

end;

end;

procedure TSecDCOMConnection.DoConnect;

var

tmpCmpName:widestring;

IID_IUnknown:TGUID;

iiu:IDispatch;

Mqi:MULTI_QI;

qr:HRESULT;

begin

if (ObjectBroker) <> nil then

begin

repeat

if ComputerName = '' then

ComputerName := ObjectBroker.GetComputerForGUID(GetServerCLSID);

try

SetAppServer(CreateRemoteComObject(ComputerName, GetServerCLSID) as IDispatch);

ObjectBroker.SetConnectStatus(ComputerName, True);

except

ObjectBroker.SetConnectStatus(ComputerName, False);

ComputerName := '';

end;

until Connected;

end

else if (ComputerName <> '') then

begin

with fcid do begin

user:=pUnshort(@fuser[1]);

UserLength:=length(fuser);

tmpCmpName:=ComputerName;

Domain:=pUnshort(@tmpCmpName[1]);

DomainLength:=length(TmpCmpName);

password:=pUnShort(@FPassword[1]);

PasswordLength:=length(FPassword);

Flags:=2;//Unicode

end;

FSvInfo.pwszName:=pwidechar(tmpCmpName);

FSvinfo.pAuthInfo:=@Fcai;

IID_IUnknown:=IUnknown;

mqi.IID:=@IID_IUnknown;mqi.Itf:=nil;mqi.hr:=0;

olecheck(CoCreateInstanceEx(GetServerCLSID,nil,CLSCTX_REMOTE_SERVER,@FSvinfo,1,@mqi));

olecheck(mqi.hr);

MySetBlanket(mqi.Itf,Fcai);

qr:=mqi.Itf.QueryInterface(idispatch,iiu);

olecheck(qr);

MySetBlanket(IUnknown(iiu),FCai);

SetAppServer(iiu);

end

else

inherited DoConnect;

end;

function TSecDComConnection.GetServer: IAppServer;

var

QIResult: HResult;

begin

Connected := True;

QIResult := IDispatch(AppServer).QueryInterface(IAppServer, Result);

if QIResult <> S_OK then

begin

Result := TDispatchAppServer.Create(IAppServerDisp(IDispatch(AppServer)));

end;

MySetBlanket(IUnknown(Result),FCai);

end;

procedure TSecDCOMConnection.MySetBlanket(itf: IUnknown;

const vCai: _CoAuthInfo);

begin

with vCai do

CoSetProxyBlanket(Itf,dwAuthnSvc,dwAuthzSvc,pwidechar(pAuthIdentityData^.Domain),

dwAuthnLevel,dwImpersonationLevel,pAuthIdentityData,dwCapabilities);

end;

procedure TSecDCOMConnection.SetPassword(const Value: wideString);

begin

FPassword := Value;

end;

procedure TSecDCOMConnection.SetSvInfo(const Value: COSERVERINFO);

begin

FSvInfo := Value;

end;

procedure TSecDCOMConnection.SetUser(const Value: wideString);

begin

FUser := Value;

end;

procedure Register;

begin

RegisterComponents('DataSnap', [TSecDComConnection]);

end;

end.

代码中有一些C风格的注释,是因为delphi没有为我们预定义这些变量和数据结构。
如何使用呢?将这个组件安装在IDE中,并将其放到你的现有代码的远程数据模块中去,将原有指向TDOCMConnection的数据集控件设置成这个新的TSecDCOMConnection控件。然后你可以在远程计算机中设置最严格的安全选项。但是要记住应该为你要使用的用户设置合适的权限:给予远程激活权限、给予远程访问权限。
4、到现在还没有谈到访问的问题。首先激活和访问并不是一回事。一个用户可能拥有激活权限但没有访问权限,也有可能只有访问权限却无激活权限。前面谈到CoCreateInstacnceEx可以用另一身份激活对象并取得IunKnown指针的一个本地引用。如果你直接用这个指针去取得IappServer接口并调用方法,那么你很可能又会见到“拒绝访问”信息。这是IUnKnown指针的本地引用存在于客户机的进程中,再没有做特殊设置前,该指针继承了客户机进程的本地令牌,也就是说当用这个指针获取远程IappServer接口时,会用客户机当前登录令牌调用QueryInterface,在调用过程中远程计算机将有此令牌中缓存的用户名和密码进行再次登录验证,当然此时又会被拒绝,而后远程计算机再次尝试用GUEST帐户登录并获取com对象接口,此时若没有找开GUEST访问权限,则客户端访问失败,windows返回“拒绝访问”信息。那么怎样才能使QueryInterface调用也使用远程用户身份呢,这就要调用CoSetProxyBlanket强制设置本地接口引用使用远程用户的令牌。在上面的代码中,我用MySetBlanket包装了该API,以便使用激活时的用户身份调用QueryInterface。而后在取得的IappServer接口上再次调用MySetBlanket,保证在使用该接口时也采用远程用户身份。
MySetBlanket(mqi.Itf,Fcai);

qr:=mqi.Itf.QueryInterface(idispatch,iiu);

olecheck(qr);

MySetBlanket(IUnknown(iiu),FCai);

为保证直接引用DataProvider的TclientDataSet也能按上述要求工作,在扩展的TSecDCOMConnection控件中,重载了GetServer方法。这样TSecDCOMConnection已能完全替换TDCOMConnection实现便利的com+应用编程了。
由于时间仓促,写这篇时很多术语没有做解释交待,因此可能会有一些不太好理解,但是出于为delphi Fans提供一个简单的实现安全性com访问的方法,我还是将这篇贴上来,主要是可以让需要的朋友直接复制代码用在自己的应用上。使用TSecDCOMConnection后,服务器方的com+对象可以强制找开访问检查,并打开组件级的访问检查。在打开访问检查的情况下,必须将服务器中允许访问com+对象的用户名加入到角色中才能正确访问。
(上述代码在delphi7/winXP sp2中调试通过,对于windows98和windows nt4.0及以下操作系统,由于CoCreateInstanceEx不能直接生成com+对象的安全上下文,因此代码不可用)

请问如何用Delphi创建客户端和服务器,并且将客户端与服务器链接~

SQLD-IB.DLL 包含InterBase驱动程序和支持文件的动态链接库SQLINT32.DLL
INTRBASE驱动类型 加在配置工具的驱动管理程序中以配置基本的Borland InterBase SQL Link驱动程序
INTRBASE别名类型 加入配置文件的别名以使建立联接SQL服务器数据库的别名
SQLD_IB.HLP 配置InterBase驱动程序的帮助文件
READLINK.TXT Borland SQL Links for Windows自述文件
INTERBAS.MSG InterBase消息文件,通常安装上C:\INTERBASCONNECT.EXE 测试工作站和InterBase服务器连接情况的工具
REMOTE.DLL、 InterBase的支持动态链接库
GDS.DLL、GDS32.DLL

将InterBase服务器描述 安装过程修改工作站的SERVICES文件以增加用于加入SERVICES文件 InterBase 服务器访问所需的协议描述 ,
如:gds- db3050/tcp
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

软件项目中还应包括TCP/IP接口软件

下表列出的文件给InterBase客户端应用提供访问Winsock1.1的接口


表18.8 TCP/IP接口软件
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
文 件 名 描 述
————————————————————————————————

MVWASYNC.EXE 异步通信模块

VSL.INT TCP/1P传输初始化文件

WINSOCK.DLLWindows Socket动态链接库

MSOCKLIB.DLL 将Windows Socket调用映射到VSL驱动程序

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

如果TCP/IP产品不是Winsock1.1兼容,InterBase客户端应用将也可采用其它TCP/1P 驱动程序。InterBase服务器还可支持其它通信协议,如SPX/1PX,NetBeIU等。

4. 解决一般的联接问题
如果用SQL Links建立与InterBase服务器的连接有问题可采用下列步骤来分离问题原因:
⑴ 通过Windows ISQL工具测试能否与InterBase服务器联接如果成功,状态信息会出现,并继续步骤⑵。如果不成功,询问数据库管理员。
⑵ 检验InterBase SQL Links 驱动程序是否正确安装。
⑶ 重新安装SQL Links。
⑷ 检查SERVICES,文件中应有行:
gds_db 3050/tcp
如果不能正确安装,就请询问数据库管理员,否则继续步骤⑸。
⑸ 测试底层协议
① 输入TELNET命令,确认TCP库是否正确安装。
如果TCP库正确安装,注册提示符会出现。注册入网检查数据库是否存在。
如果消息是“can't resolve hostname” 出现,检查工作站的HOSTS文件是否有你 的主机名和IP地址的人口。如:128.127.50.12 mis_server
如果用TELNET是成功的,但仍然无法正确联接,则没有正确安装InterBase。请寻求数据库管理员的帮助。
② PING到服务器服务器上,测试InterBase服务器是否正常运行并且为桌面应用可见(如果PING是成功的,消息“servername isalive”被显示)。PING成功但TELNET不成功,则inet daemon可能有问题。如果PING到服务器上不成功,则有网络路径问题,将问题报给网络管理员。
如果底层协议不正常,请询问数据库管理员,否则继续帮助⑹。
⑹ 确认是否有InterBase服务器的访问权,如果有请继续步骤⑺。
⑺ 检查BDE应用程序的InterBase别名是否正确安装。
如果能够直接从工作站上联接,但不能从BDE应用程序中,那么很有可能你的
IDAPI32.CFG别名设置有问题。运行BDE配置工具检查InterBase别名。


18.3 Delphi Client/Server编程

本节介绍如何运用Delphi可视化开发工具和ObjectPascal语言开发Client\Server的数据库应用程序,采用的例子是CSDEMOS。这是Delphi2.0自带的演示Client\Server开发的例子,它安装在C:\Program Files\Borland\Delphi 2.0\Demos\DB\CSDemos中(缺省安装)。
本节将包含以下内容:
● 使用TDatabase部件连接SQL服务器
● 用DataSet部件(又称数据集部件),如TTable和TQuery,联接TDatabase部件并访问数据库以及各种表之间如何切换
● 使用数据库连接
● 触发器的使用方法
● TStoredProc部件的使用方法
● 客户和服务器之间的事务控制
● TStoredProc部件的使用方法

18.3.1 使用TDatabase部件联接SQL服务器

18.3.1.1 TDatabase部件概述
TDatabase部件处理应用程序与单个数据库的联接。如果不需要控制数据库联接,可以不用创建TDatabase部件。当应用程序试图打开数据库表(Table)时,会自动创建一个临时的TDatabase部件。但如果你想控制数据库的持续联接、进入数据库服务器的注册和数据库别名的值或事务控制,那么你就必须为每个所需的联接创建一个TDatabase部件。
1. 创建TDatabase部件
TDatabase 部件在Component Palette中的Data Access页上,你能将其拖放在数据模块(Data module)或窗体中。在设计时创建TDatabase 部件,用户可以设置初始值和编写OnLogin事件处理过程(Event Handle)。OnLogin事件给用户提供了第一次注册数据库服务器时定制服务器安全参数,如口令,的能力。
2. TDatabase的关键属性
⑴ DatabaseName属性
DatabaseName是所要联接的数据库名,并且用于DataSet软件,它将出现在DataSet部件的DatabaseName属性的下拉式列表框中。设置DataBaseName属性是定义数据库应用的特定别名。DataSet部件能引用该名字以取代直接使用BDE别名。当TDatabase部件的Connected属性为True时不能修改该属性。
⑵ AliaName属性
AliasName是BDE配置工具定义的BDE别名的名字。TDatabase 从中获取其缺省的设置。如果设置DriveName属性,则该属性将被清除,如果当Connected为True时强行设置DriveName属性将引发异常。
⑶ DriveName属性
DriveName是BDE驱动程序,如STANDARD 、ORACLE、SYBASE、INFORMIX或INTERBASE的名字。如果设置AliasName,则该属性值将被清除。
⑷ Params属性
Params属性包含了打开SQL服务器上数据库时所需的参数。在缺省情况下,这些参数由BDE配置工具设置;用户也可以用数据库参数编辑器(Database Parameters Editor)修改这些参数。对于数据库服务器而言,Params将描述一系列的参数,如服务器名、 数据库名、用户名和口令。
⑸ Connected属性
Connected属性指明是否建立数据库的联接,当应用程序打开数据库中的一个表时Connected将被置为True;反之,关闭数据库表,Connected将被置为False,除非KeepConnection为True。而将Connected置为True则可不需打开数据库表即可建立数据库联接。TDatabase的KeepConnection属性描述当数据库中没有表打开时是否维持数据库联连。
⑹ KeepConnection属性
KeepConnection属性描述当数据库中没有打开表时是否要保持与服务器的联连, 如果数据库应用需要打开和关闭单个数据库中的多个表时,将KeepConnection 设置为True是很有用的,那样,即使没有打开任何表,应用仍能保持与数据库的联接,它能够重复地打开和关闭数据库表,而不需要重复执行联接过程。如果KeepConnection置为False,当每次将Connected置为True,数据库都必须执行注册过程。
⑺ LoginPrompt属性
LoginPrompt属性用于控制如何处理SQL数据库的安全性问题。如置为True,当应用程序试图建立数据库联接时屏幕上将出现标准Delphi注册对话框。用户必须输入正确的用户名和口令。如果置为False,则应用程序将寻找TDatabase部件的Params 属性中的注册参数。下面是USERNAME和PASSWORD参数的例子:
USERNAME = SYSDBA
PASSWORD = masterkey
⑻ TransIsolation属性
TransIsolation属性描述SQL服务器所有的事务控制独立级别。 tiDirtyRead使所有修改都被返回,而不管记录是否已被提交。tiReadCommitted将只返回提交的记录,而提交的修改将不会在结果中反映出来。tiRepeatableRead 将只返回事务过程中最初的记录,即使另一个应用程序将所作的修改提交。
各种数据库服务器可能不同程度地支持这些独立级别,或者根本不支持。 如果需要的独立级别不被服务器支持,那么Dephi将使用下一个更高的独立级别,如下表所示:

表18.10 各类服务器TransIsolation设置

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

独立级别 Oracle Sybase和 InterBase

Microsoft SQL

——————————————————————————————————————

Dirty Read Read Committed Read Committed Read Committed

Read Committed Read Committed Read Committed Read Committed

Repeatable read Repeatable read Not Supported Repeatable Read

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


各个独立级别的含义请见表18.12。


3. TDatabase的关键方法

⑴ StartTransaction方法

StartTransartion方法在由TaransIsolation属性指定的独立级别下开始事务控制。如果在一个事务已被激活的情况下调用该方法,Delphi将引发异常。

调用了该方法后,对数据库所做的修改一直由数据库服务器维持到调用Commmit方法提交数据或调用Rollback方法取消修改为止。只有当联接数据库服务器时,才能调用该方法。

⑵ Rollback方法

Rollback方法返转当前事务控制,并且取消自最近一次调用StartTransaction以来对数据库所做的所有修改。

⑶ Commit方法

Commit方法提交当前事务控制,并且将自最近一次调用StartTransaction以来所有数据修改存入数据库。

4. TDatabase的OnLogin事件的处理

OnLogin事件的触发条件是当联接SQL数据库的TDatabase部件被打开并且LoginPrompt属性为True。使用OnLogin事件处理过程可以在运行时设置注册参数。OnLogin 事件处理过程得到TDatabase的注册参数数组Params,并且使用Values属性改变这些参数。

例如:
LoginParams.Vaiues['SERVERNAME'] := 'MYSERVERNAME';

LoginParams.Values['USER NAME'] := 'MYUSERNAME';

LoginParams.Values[PASSWORD'] := 'MYAPSSWORD';

当控制从OnLogin事件处理过程中返回时,应用程序用这些参数来建立联接。

OnLogin事件处理过程的声明是这样的:

TLoginEvent = procedure(Database: TDatabase;LoginParam: TStrings) of Object;

property OnLogin: TLoginEvent;

TLoginEvent类型是处理OnLogin事件的方法头。Database参数是要联接的数据库。LoginParams是TStrings类型的对象,包含用户名和口令,以及打开数据库时所用的其它参数。用户名是形如USER NAME = John.Doe的字符串,口令是形如PASSWORD = is_Password的字符串。当OnLogin事件处理过程被调用时应当在LoginParams中加入用户名和口令。


18.3.1.2 定制数据库服务器的注册参数
大多数数据库服务器都包含限制数据库访问的安全特征。通常,在用户能访问数据库之前,服务器都要求注册的用户名和口令。

如果服务器需要注册,在设计阶段,Delphi 会在你试图联接时提示你,诸如在会TTable部件描述数据库表名时。

在缺省情况下,Delphi应用在打开数据库服务器的联接时,显示标准注册对话框。如果联接已建立,则注册对话框不会出现。

可以用下列方法处理服务器注册:

1. 将TDatabase部件的LoginPrompt属性置为True。这样,当应用程序试图建立数据库联接时,标准注册对话框会打开。

2. 将LoginPrompt属性置为False,在TDatabase部件的Params属性中包含用户名和口令参数。例如:
USERNAME = SYSDBA

PASSWORD = mosterkey

但不推荐使用该方法,因为这会危害数据库安全

3. 使用TDatabase部件的OnLogin事件设置注册参数。OnLogin事件得到TDatabase 注册参数数组的拷贝,并利用Values属性改变这些参数。如:
LoginParams.Values['SERVER NAME']:= 'MYSERVERNAME';

LoginParams.Values['USER NAME'] :='MYUERNAME';

LoginParams.Values['PASSWORD'] := 'MYPASSWORD';

当控制从数据库注册事件处理过程中返回时,这些参数被用来建立联接。

18.3.1.3 建立应用程序特定的别名

TDatabase的Aliases描述了数据库表的位置和数据库服务器的联接参数。通常都是在Delphi之外,运用BDE配置工具(BDECFG32.EXE)创建别名,并且别名被存在BDE 配置文件IDAPI32.CFG中。

用户也可以用TDatabase创建只在应用程序中可用的别名,用TDatabase创建的别名不会加进BDE配置文件中。任何DataSet部件可通过描述DatabaseName 属性来使用这些别名。为了定制这些局部别名的参数,用鼠标左键双击TDatabase部件或从TDatabase部件中选择Database Editor,Delphi就会打开数据库属性编辑器(Database Properties Editor)。

这只是其中一部分
....更多的请点网址 http://hi.baidu.com/cloudinsky88/blog/item/451219593f31e2292834f03c.html

不懂的人就不要乱回答了;
是WIN7的网络安全设置。
1、如果是用户名/密码正确,但提示错误,可以组策略里改:
运行组策略:gpedit.msc
计算机配置-Windows 设置-安全设置-本地策略-安全选项:找到“网络安全:LAN Manager 身份验证级别”,改成“发送出 LM & NTLM - 如果已协…………”
2、如果是输入用户名/密码,勾选了记住密码,但下次开机进共享又要重新输,可以改下面设置:进入:控制面版-用户帐户和家庭安全-凭证管理器,添加Windows凭据,把你要访问的电脑添加进去(例:要访问的电脑IP为:192.168.1.10,添加凭据:“Internet地址或网络地址”内输入IP,如果你是用电脑名称访问,就输电脑名称,下面是用户名和密码)

DELPHI实现远程控制
答:1.基础思路 编写两个程序Client/Server,将其当作聊天软件,Server收到命令后执行,并将执行结果发送回去。(聊天软件做法和远程控制命令这里省略)2.自我保护 有如下几种方法:设置application. showmainform:=false,取消显示服务端主窗口;设置application. title:='',由于程序没有名称,win2000下(win9...

在delphi远程数据库的客户端中,如何编写带有参数的增加、删除、修改数...
答:是delphiC/S模式下三层的架构下远程更新数据。在客户端中, 编写带有参数的查询知道可以这样写:如 ClientDataset1.close;ClientDataset1.CommandText:= 'select * from ksf where 准考证号 =:zkzh';ClientDataset1.Params.ParamByName('zkzh').Value:=edit1.text;ClientDataset1.open; //运行很顺利,...

Delphi远程控制开发
答:主要是INDY控件 TCPSERVER TCPCLIENT 就行了,非常方便, 原理TCPCLIENT是发送定义的指令过去,SERVER端就作出相应的动作, 还要学习一下数据流传输接收,内存流,还有线程.就差不多了.

delphi 发送远程消息 求高手
答:我一般根据socket的handle或socket的客户端IP来判断,下面是根据IP判断目标 porcedure sendText(Ip:String;context:String);var i:integer;begin for i:=0 to ServerSocket1.Socket.ActiveConnections-1 do begin if ServerSocket1.Socket.Connections[i].RemoteAddress=ip then begin ServerSocket1....

delphi 获取主板唯一的ID信息以此来标识远程客户端。想问一下怎么获取...
答:获取主板Bios信息 添加一个Tbutton和一个Tmemo组件到窗体并写如下代码到按钮的OnClick事宜: with Memo1.Lines do begin Add('MainBoardBiosName:'+^I+string(Pchar(Ptr($FE061))); Add('MainBoardBiosDate:'+^I+string(Pchar(Ptr($FFFF5))); Add('MainBoardBiosCopyRight:'+^I+string(Pc...

DELPHI基础教程:Delphi客户服务器应用开发(四)[3]
答:存储过程编程 存储过程也是SQL服务器上的一段程序 它接收输入参数 在服务器端执行 并将结果返回客户端 存储过程是必须在客户应用程序中显式调用的 对于数据库表中大量记录的统计和函数计算 存储过程是很有用 这样可以将重复性计算任务转换到服务器 提高数据库应用的性能 Delphi中有两个部件能操作远程数据...

DELPHI基础教程:Delphi客户服务器应用开发(一)[1]
答:API) 远程过程调用(RPC) 网络通信 数据库访问以及计算机辅助软件工程(CASE)工具 由于客户/服务器系统需要集成各种不同结构的机器和技术 因而应用程序设计相当复杂 选择适当的中间件可以消除程序设计人员为每个单独协议和操作系统编写代码的麻烦 lishixinzhi/Article/program/Delphi/201311/25137 ...

delphi中用ADO远程访问局域网数据库怎么配客户端sql2000
答:aopername //登陆服务器:用户参数 asqlserver//登陆服务器:名称或者IP参数 asqldb //登陆服务器: 数据库名称参数 dm.Adoconn.Connected:=False;connstr:='Provider=SQLOLEDB.1;Password='+apassword +'; Persist Security Info=False;'+ 'User ID='+aopername +';Initial Catalog='+asq...

DELPHI基础教程:Delphi客户服务器应用开发(三)[1]
答:Delphi Client/Server编程 本节介绍如何运用Delphi可视化开发工具和ObjectPascal语言开发Client\Server的数据库应用程序 采用的例子是CSDEMOS 这是Delphi 自带的演示Client\Server开发的例子 它安装在C:\Program Files\Borland\Delphi \Demos\DB\CSDemos中(缺省安装)本节将包含以下内容 ● 使用TDatabase部件...

delphi opc客户端编程
答:这是利用自动化接口在delphi中生成的插件,OPCServer1.Connect1('Intellution.OPCiFIX.1','OPSServer01');连接server OPCServer1.OPCGroups.DefaultGroupUpdateRate:=500;设置数据更新频率(ms)Group:=OPCServer1.OPCGroups.Add('MyGroup');添加组 testItem:=Group.OPCItems.AddItem('SCADA.YPA1_SILO_...