C#中的Windows凭据提供程序

3
我正在进行一个学校项目,需要修改Windows登录UI中提供凭据的方式。经过一些搜索,我找到了著名的Vista RTM(Longhorn)示例和技术文档。我发现所有示例都是用C++开发的。
由于我没有任何C/C++经验,而我认为自己是一位不错的C#程序员,所以我想知道是否可以使用C#来完成这个任务。
我还需要与REST API交换数据以验证登录,所以C#会更友好。
我找到了这个https://dev59.com/RmQo5IYBdhLWcg3wZelg#23496878,但@mageos提供的信息太“生硬”了。
有人知道一些有用的资源吗?

1
http://pgina.org/,编写插件是最简单的方式,假设允许这样做。 - Alex K.
很遗憾,这不是@Alex K. 这是我的第一种方法,但我没有被允许。 - loveMeansNothing
你能找到有用的东西吗,@loveMeansNothing?我也是同样的情况。 - Nitin Khubani
1个回答

12

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

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

注意:您需要将所有定义包装到"library CredentialProviders { ... }"语句中,否则只有一些类型会被导出。

使用VS本机工具打开并使用midl编译:

midl "C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\credentialprovider.idl"

这将创建一个类型库(tlb文件),然后.NET可以使用它将类型转换为C#类型。现在可以使用tlbimp实用程序创建Interop dll,然后您可以在.NET中使用它:

tlbimp.exe credentialprovider.tlb /out:CredentialProvider.Interop.dll

但是由于tlbimp不支持返回类型的转换,我们需要使用tlbimp2来解决这个问题:

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下添加一个键来注册此凭据提供程序,并以组件的实现GUID(记住这里的大括号)命名。

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

现在,在所有这些步骤之后,我们仍然需要实现凭据提供程序。这最好在一份名为Credential Provider driven Windows Logon Experience的文档中描述。您最终需要协调UI与可能需要在后台执行的任何事情,并将其映射到用户。

当正确序列化用户信息时,您将能够登录用户,该信息位于方法实现ICredentialProviderCredential::GetSerialization中。

示例

我已经制作了一个示例,您可以在此处找到它:https://github.com/phaetto/windows-credentials-provider


你能帮我看一下我的问题吗?https://dev59.com/434QtIcB2Jgan1znq3mY - candogg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接