2016-04-05 125 views
1

我正在学校项目中,我应该修改在Windows登录UI中提供凭据的方式。 经过一番搜索后,我找到了着名的Vista RTM(Longhorn)样本和技术文档。我发现所有的样本都是用C++开发的。C#中的Windows凭据提供程序#

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

我还需要与REST API交换数据以验证登录,所以C#会更友好。

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

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

+1

http://pgina.org/和编写插件是最简单的方法,这就是假定允许的。 –

+0

不幸的是它不是@Alex K. 这是我的第一个方法,但我没有被允许。 – loveMeansNothing

+0

您是否能找到有用的@loveMeansNothing?我也在同一条船上 –

回答

2

您提供的链接完全正确。您需要在.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本地工具和编译与midlmidl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl"

这将创建一个类型库(tlb文件),然后.NET可以使用它来将类型转换为C#类型。您现在可以使用tlbimp实用程序来创建那么您可以在.NET中使用互操作的dll: tlbimp.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll

捕捉#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接口完全相同。

在执行:从所有方法E_NOTIMPL

[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; 
    } 

    ... 
} 

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

您可以通过在注册表设置HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\Credential Providers下添加一个用组件的实现guid命名的密钥来注册此凭据提供程序(请在此记住括号)。

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

现在,在完成所有这些步骤之后,我们仍然需要实施凭证提供程序。这最好在名为Credential Provider driven Windows Logon Experience的文档中描述。您最终需要用任何可能的事情编排UI,以便在后台执行此操作并将其映射到用户。

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

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

相关问题