如何使用COAUTHIDENTITY在CoCreateInstanceEx中正确模拟其他用户?

时间:2012-06-11 20:34:25

标签: windows-authentication dcom

我目前正在开发一个MFC应用程序,它需要从另一个系统上运行的COM对象中检索数据。当两个系统都运行Windows XP并且手动设置相同的用户帐户(即两个系统上都有相同的用户名和密码,没有域)时,我们已经有了相同的数据交换机制,并且完全支持。麻烦的是,我正在设置它,以便我可以从另一台具有相同用户帐户设置的计算机访问同一个DCOM系统,但是在公司域用户帐户下登录。

现在,如果我使用运行方式手动运行我的应用程序并指定备用用户,它可以工作,但我正在寻找更好的解决方案。当我在CoCreateInstanceEx中为COSERVERINFO设置COAUTHIDENTITY时,我指定备用帐户的用户名和密码,这似乎不起作用。我在域名条目中尝试了各种各样的东西 - 本地计算机的计算机名称,远程计算机的计算机名称,并将其留空 - 但似乎没有任何帮助。

我尝试编辑服务器计算机上对象的DCOM权限,以允许完全访问Everyone帐户,但这似乎没有帮助,而且我无法找到任何有意义的错误消息错误。如果我可以在服务器计算机上获得某种日志消息,以便在使用“运行方式”运行它时确切地查看所发生的凭据,这可能会有所帮助。有人有什么想法吗?或者,当您从非域帐户进行DCOM连接时,可能知道系统使用Domain的内容(有些事情意味着使用了计算机名称,但是当我尝试使用时这不起作用)。

代码如下:

COAUTHINFO      AuthInfo;
COAUTHIDENTITY  AuthIdentity;
COSERVERINFO    ServerInfo;
MULTI_QI        Results;    

AuthIdentity.Domain             = (unsigned short *) w_domain;
AuthIdentity.DomainLength       = wcslen( w_domain);
AuthIdentity.Flags              = SEC_WINNT_AUTH_IDENTITY_UNICODE;
AuthIdentity.Password           = (unsigned short *) w_password;
AuthIdentity.PasswordLength     = wcslen(w_password);
AuthIdentity.User               = (unsigned short *) w_username;
AuthIdentity.UserLength         = wcslen(w_username);

AuthInfo.dwAuthnLevel           = RPC_C_AUTHN_LEVEL_CALL; 
AuthInfo.dwAuthnSvc             = RPC_C_AUTHN_WINNT; 
AuthInfo.dwAuthzSvc             = RPC_C_AUTHZ_NONE;
AuthInfo.dwCapabilities         = EOAC_NONE;
AuthInfo.dwImpersonationLevel   = RPC_C_IMP_LEVEL_IMPERSONATE;
AuthInfo.pAuthIdentityData      = &AuthIdentity;
AuthInfo.pwszServerPrincName    = NULL;

ServerInfo.dwReserved1  = 0;
ServerInfo.dwReserved2  = 0;
ServerInfo.pAuthInfo    = &AuthInfo;
ServerInfo.pwszName     = w_nodename;

Results.pIID = &_uuidof(_DS_SessionContext);
Results.pItf = NULL;
Results.hr   = 0;

hr = CoCreateInstanceEx(clsid, NULL, CLSCTX_ALL, &ServerInfo, (ULONG) 1, &Results);                             
if(FAILED(hr))
{
    m_Error.Format("(0x%x) CoCreateInstanceEx for _DS_DataFrame failed.",hr);
    m_Error2.Format("Make sure computer IP address is correct and connected.");
    CoUninitialize();
    UpdateData(false);
    UpdateWindow();
    return false;           
}

pSession = (_DS_SessionContext *)Results.pItf;

hr = pSession->raw_DS_GetVersion(&DSStatus, &version);
if(FAILED(hr))
{
    m_Error.Format("(0x%x)GetVersion",hr);
    CoUninitialize();
    UpdateData(false);
    UpdateWindow();
    return false;           
}

1 个答案:

答案 0 :(得分:0)

啊,我想通了。事实证明,在DCOM中,在其上创建实例和调用函数不会自动使用相同的安全毯。传递给CoCreateInstanceEx的COSERVERINFO中的身份验证信息仅适用于创建实例,当我稍后调用该实例上的函数时,它会失败,因为我使用应用程序的凭据调用这些函数。

为了正确地做到这一点,在调用实例上的函数之前,我必须先调用(为清楚起见省略了错误处理):

    hr = CoSetProxyBlanket(Results.pItf, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, 
    RPC_C_IMP_LEVEL_IMPERSONATE, &AuthIdentity, EOAC_NONE);

这将用于调用实例的安全毯设置为用于创建实例的安全毯,因此一切正常。