lov*_*ing 1 c# c++ windows winapi credential-providers
我正在处理一个学校项目,该项目应该修改Windows登录UI中提供凭据的方式。经过一些搜索,我找到了著名的Vista RTM(Longhorn)样本和技术文档。我发现所有示例都是用C ++开发的。
由于我没有任何C / C ++经验,并且我认为自己是一位体面的C#程序员,因此我想知道是否可以执行此C#。
我还需要与REST API交换数据以验证登录名,因此C#会更加友好。
我已经找到了这个/sf/answers/1644781491/,但是@mageos提供的信息太“原始”了。
有人知道一些有用的资源吗?
小智 6
您提供的链接是完全正确的。您将需要在NET中实现一个COM对象,该对象至少实现以下两个COM接口:ICredentialProvider,ICredentialProviderCredential
首先,您必须在.NET中公开它们,以便您可以引用它们。以我的经验,最简单的方法是通过Windows SDK中的IDL。您将需要的idl文件为\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl。
捕获#1:您需要将其中的所有定义包装到该library CredentialProviders { ... }语句中,否则只有某些类型可以导出)
打开VS本机工具,并使用进行编译midl:
midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl"
这将创建一个类型库(tlb文件),然后.NET可以使用该类型库将类型转换为C#类型。现在,您可以使用该tlbimp实用程序创建一个互操作dll,然后可以在.NET中使用它:
tlbimp.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll
第2个要点:tlbimp不幸的是,带有的编译剥离了方法调用(HRESULT)的返回类型,并希望您使用.NET异常子系统。在这种情况下,这将不起作用,因为Winlogon(或credUI主机应用程序)会抛出异常并终止进程。解决方案是使用名为的实用程序tlbimp2。在撰写本文时,它已在SVN托管在codeplex上-仅提供代码。我必须下载代码并在VS2017中重新编译该工具(我已在附件存储库中上传了工件)。因此,我们需要运行以下命令才能编译winlogon:
tlbImp2.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll /unsafe /verbose /preservesig
现在我们可以启动一个可以实现COM对象的库。在.NET Framework中启动一个dll项目。编辑项目,并确保选中“注册COM互操作”标志。参考编译的Interop库。
如前所述,我们将需要实现两个接口:ICredentialProvider,ICredentialProviderCredential。该代码应如下所示:
[ComVisible(true)]
[Guid("<random-guid>")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface ITestWindowsCredentialProvider: ICredentialProvider
{
}
Run Code Online (Sandbox Code Playgroud)
您可以对ICredentialProviderCredential接口执行完全相同的操作。
关于执行:
[ComVisible(true)]
[Guid("<another-unique-id>")] // <-- This is what we are going to use for registration
[ClassInterface(ClassInterfaceType.None)]
public class TestWindowsCredentialProvider : ITestWindowsCredentialProvider
{
private const int E_NOTIMPL = unchecked((int) 0x80004001);
...
public int SetSerialization(ref _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION pcpcs)
{
return E_NOTIMPL;
}
...
}
Run Code Online (Sandbox Code Playgroud)
从所有方法返回E_NOTIMPL并在所有out参数中提供值。现在我们有了一个可以开始的基础对象。您可以延迟实现ICredentialProviderCredential,直到实现方法ICredentialProvider :: GetCredentialAt。
您可以通过在注册表设置下添加一个HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers使用组件的实现guid命名的注册表项来注册此凭据提供程序(请记住此处的括号)。
当您这样做时,登录服务和credUI调用将加载并查询您的组件。但是要警告:任何异常都会使winlogon崩溃,使您无法登录。使用VM作为最佳实践。
现在,在完成所有这些步骤之后,我们仍然需要实现凭证提供程序。在名为“ 凭据提供程序驱动的Windows登录体验”的文档中对此进行了最好的描述。最终,您将需要用后台需要做的任何可能的事情来编排UI,并将其映射到用户。
在方法实现ICredentialProviderCredential :: GetSerialization上正确序列化用户信息时,您将能够登录用户。
例我已经做了一个例子,您可以在这里找到它:https : //github.com/phaetto/windows-credentials-provider