WCF 服务中的模拟和传播到 COM 对象

Posted

技术标签:

【中文标题】WCF 服务中的模拟和传播到 COM 对象【英文标题】:Impersonation in WCF Service and propagating to COM object 【发布时间】:2010-09-07 00:15:07 【问题描述】:

我正在尝试创建一个 WCF 服务来公开一些服务。在其中一个合同中,我必须模拟另一个用户并调用 COM 对象。我知道如果我想将模拟传播到 COM 对象中,我应该在任何封送处理之前调用 CoInitializaSecurity。

int result = CoInitializeSecurity(IntPtr.Zero, -1,
 IntPtr.Zero, IntPtr.Zero,
            RpcAuthnLevel.Connect, RpcImpLevel.Impersonate,
            IntPtr.Zero, EoAuthnCap.DynamicCloaking, IntPtr.Zero);

但它返回 80010119,这意味着 RPC_E_TOO_LATE。

我知道这意味着 CoInitializeSecurity 已被调用。但我想将此函数称为合同中的第一条指令。即使在服务的构造函数中,我也尝试过调用 CoInitializeSecurity,但它返回相同的错误。 这意味着 WCF 内置代码包含 CoInitializeSecurity,我无法再次运行此功能。

我想调用一个 com 对象,并且我想让 com 对象在 C# 中与模拟用户一起工作,但如果我成功调用 CoInitializeSecurity,这意味着 COM 对象将不会由模拟用户运行。


@Remus Rusanu 回答后刚刚添加

我已经创建了如下服务合同

   [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string GetData()
    
        MyComClass comObj = new MyComClass();
        string ComUser = comObj.GetLogOnUser();
        return System.Security.Principal.WindowsIdentity.GetCurrent().Name + " " + ComUser;
    

在客户端,我通过所需的凭据调用了此服务

    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
    client.ClientCredentials.Windows.ClientCredential.Domain = "Domain";
    client.ClientCredentials.Windows.ClientCredential.UserName = "DomainUser";
    client.ClientCredentials.Windows.ClientCredential.Password = "passw0rd";
    string str = client.GetData();

结果是

DOMAIN\DomainUser DOMAIN\CurrentUser

这意味着 WCF 已模拟 DomainUser 但 COM 对象内部仍在与以前的用户合作。

【问题讨论】:

【参考方案1】:

托管主机已经在为您初始化 COM。您不必重新初始化线程 COM 安全性。只需在 WCF 中模拟(例如,通过[OperationBehavior(Impersonation=ImpersonationOption.Required)])并使 COM 对象实例化,它将在模拟上下文中发生。并不是说如果 COM 对象是远程的,那么就会发生约束委派,并且您的 WCF 主机进程必须配置为约束委派。

见How to: Impersonate a Client on a Service、Delegation and Impersonation with WCF和Enabling Delegated Authentication

【讨论】:

感谢您的回复。我还没有尝试过,但据我所知,我必须通过 您冒充 WCF 服务的调用者。如果您想模拟不同的用户,那么您必须 LogonUser 该凭证(请参阅 msdn.microsoft.com/en-us/library/chf6fbt4.aspx 的示例),然后使您的 COM 对象实例化。但是冒充用户/密码通常是一种不好的做法,一个好的设计应该使用调用者的凭据,或者服务凭据,但永远不要使用显式凭据,因为 pf 密码存储问题。 实际上我已经根据您的建议更新了问题,但 COM 对象没有从调用者那里获取信息。我在控制台应用程序中体验过这一点,并通过调用 CoInitializeSecurity 它工作。但不幸的是,在这种情况下,我无法再次调用 CoInitializeSecurity。 通过声明ImpersonationOption.NotAllowed,您所做的与您声明需要做的完全相反:您明确忽略客户端提供的凭据。 复制粘贴错误!固定的。实际代码由 ImpersonationOption.Required 参数编写。

以上是关于WCF 服务中的模拟和传播到 COM 对象的主要内容,如果未能解决你的问题,请参考以下文章

WCF 服务中的无意模拟

在声明身份验证的 SharePoint 2010 中托管的 WCF 服务中的模拟

WCF 模拟和 SQL 可信连接?

自托管 WCF 中的模拟?

在 WCF 服务中使用模拟时 SQL 登录失败

在模拟上下文之外调用 WCF 服务?