C#中的Windows凭据提供程序

我正在做一个学校项目,我应该修改Windowslogin界面提供的凭据方式。 经过一番search,我find了着名的Vista RTM(Longhorn)样本和技术文档。 我发现所有的样本都是用C ++开发的。

由于我没有任何C / C ++的经验,我认为自己是一个体面的C#程序员,我想知道是否有可能做这个C#。

我还需要与REST API交换数据来validationlogin,所以C#会更友好。

我发现这个https://stackoverflow.com/a/23496878/3626447 ,但由@mageos提供的信息太“原始”。

有人知道一些有用的资源吗?

你提供的链接是完全正确的。 您将需要在NET中实现一个COM对象,实现以下两个COM接口(至少):ICredentialProvider,ICredentialProviderCredential

首先,您将不得不在.NET中公开它们,以便引用它们。 根据我的经验,更简单的方法是通过Windows SDK中的IDL。 您需要的idl文件将是\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl

Catch#1:您需要将所有定义包含在library CredentialProviders { ... }语句library CredentialProviders { ... } ,否则只有一些类型会被导出)

打开您的VS本机工具,并使用midlmidl "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

Catch#2:tlbimp编译不幸的是剥离了方法调用( HRESULT )的返回类型,并希望使用.NET异常子系统。 由于winlogon(或credUI主机应用程序)重新抛出异常并终止进程,因此在这种情况下不起作用。 解决方法是使用名为tlbimp2的实用程序。 在编写这个代码的时候,它是在codeplex上托管的 – 只有代码是可用的。 我不得不下载代码并重新编译VS2017中的工具(我上传了附件中的工件)。 所以我们需要运行这个为了编译winlogon: tlbImp2.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll /unsafe /verbose /preservesig

现在我们可以启动一个库来实现COM对象。 在.NET框架中启动一个dll项目。 编辑项目并确保选中“注册COM互操作”标志。 参考已编译的Interop库。

如前所述,我们将需要实现两个接口:ICredentialProvider,ICredentialProviderCredential。 代码应该如下所示:

 [ComVisible(true)] [Guid("<random-guid>")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface ITestWindowsCredentialProvider: ICredentialProvider { } 

您可以为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; } ... } 

从所有方法返回E_NOTIMPL并提供所有out参数的值。 现在我们有一个可以开始的基础对象。 您可以延迟ICredentialProviderCredential的实现,直到您实现ICredentialProvider :: GetCredentialAt方法。

您可以通过在注册表设置HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers下添加一个密钥来注册此凭证提供HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers (在此记住括号)。

当你这样做时,登录服务和credUI调用将加载和查询你的组件。 不过要注意的是: 任何异常都会导致winlogon崩溃,导致无法登录 。 使用虚拟机作为最佳实践。

现在,在完成所有这些步骤之后,我们仍然需要实施凭证提供者。 最好在一个名为Credential Provider驱动的Windows登录体验的文档中描述。 您将最终需要编排用户界面与任何可能的事情,你需要在后台做,并映射到用户。

在正确序列化方法实现ICredentialProviderCredential :: GetSerialization的用户信息时,您将能够登录用户。

我已经做了一个这样的例子,你可以在这里找到它: https : //github.com/phaetto/windows-credentials-provider